ميډياويکي:Gadget-OrangeLinks.js
يادښت: د غوره توبونو د خوندي کولو وروسته، خپل د کتنمل (بروزر) ساتل شوې حافظه تازه کړی.
- فايرفاکس/ سفري: په دې کتنمل کې د Reload د ټکوهلو په وخت د Shift تڼۍ نيولې وساتی، او يا هم Ctrl-F5 يا Ctrl-Rتڼۍ کېښکاږۍ (په Apple Mac کمپيوټر باندې ⌘-R کېښکاږۍ)
- گووگل کروم: په دې کتنمل کې د Ctrl-Shift-R تڼۍ کېښکاږۍ (د مک لپاره ⌘-Shift-R)
- انټرنټ اېکسپلورر: په دې کتنمل کې د Refresh د ټکوهلو په وخت کې د Ctrl تڼۍ کېښکاږلې ونيسۍ، او يا هم د Ctrl-F5 تڼۍ کېښکاږۍ
- اوپرا: په دې کتنمل کې د خپل براوزر ساتل شوې حافظه پدې توگه سپينولی شی Tools→Preferences
/*jshint loopfunc:true,latedef:true,undef:true */
/*globals mw, jQuery */
(function(){ // <nowiki>
'use strict';
/**
* General idea: for each bluelink with an anchor, the script fetches the categories for its target page
* and checks whether it contains a part-of-speech category. If a suitable category is found, the script
* assumes the anchor is valid. If not, the link is coloured orange.
*
* Previous version by [[User:Yair rand]], based in turn on an idea by [[User:Hippietrail]].
* This script is a complete rewrite.
*/
var api = new mw.Api();
var fresh = [], queue = {}, catcache = {};
var rxPage = new RegExp('^' + mw.config.get('wgArticlePath').replace(/([.+*?[\]$^])/g, '\\$1').replace('\\$1', '(.*)') + '$'); // hax
var console = mw.util.getParamValue('debug') ? window.console : null;
function processLink(link) {
try {
if (link._ORANGED === link.href) // XXX: eliminate this hack
return;
if (/(un)?selectedTab/.test(link.parentNode.className)) // XXX: skip TabbedLanguages tabs; is there no other way?
return;
if (!link.href || /^javascript:/.test(link.href))
return;
var m, url = new mw.Uri(link.href);
if (url.getAuthority() !== location.hostname)
return;
if (!url.fragment || !/^[A-Zǃ]/.test(url.fragment)) // XXX: "ǃ" is for nmn (Xoo); I hope there are no other such pathological language names...
return;
// XXX: exclude non-language headers
if (/^(Noun|Proper_noun|Verb|Adjective|Adverb|Participle|Interjection|Particle|Suffix|Prefix|Symbol|Phrase|Prepositional_phrase|Han_[ct]|Hanja|Hanzi|Kanji|Romanization|Gismu|Rafsi|Brivla|Idiom|Acronym|Initialism)/.test(url.fragment))
return;
if (/^(Etymology|Pronunciation|Alternative_forms|See_also|External_links|Derived_terms|Related_terms|Coordinate_terms|Descendants|Inflection|Declension|Conjugation|Usage_notes|Translations|References|Anagrams|Synonyms|Antonyms|Meronyms|Holonyms|Hyponyms|Hypernyms|Quotations|Statistics)/i.test(url.fragment))
return;
// skip local links
if (/^#/.test(link.getAttribute('href'))) {
if (console) console.warn('skipping local ', link);
return;
}
if (!(m = rxPage.exec(url.path)))
return;
var title = new mw.Title(decodeURIComponent(m[1] + '#' + url.fragment));
if (title.getNamespaceId() !== 0)
return;
var cache = catcache[title.getPrefixedText()];
if (cache) {
link._ORANGED = link.href;
var frag = title.fragment.replace(/-[a-z].*$/, ''); // XXX: {{senseid}} hack
frag = decodeURIComponent(frag.replace(/\.([0-9A-Fa-f][0-9A-Fa-f])/g, '%$1'));
for (var i = 0; i < cache.length; ++i) {
if (cache[i].substr(0, frag.length) === frag) {
// XXX: discount "German Low German", etc. but allow "Vietnamese Han tu" and "Vietnamese Nom" to count as an existing vi entry
// XXX: use /^ (lemmas|non-lemma forms)$/ instead?
if (/^ ([a-z]|Han tu|Nom)/.test(cache[i].substr(frag.length)))
return;
}
}
link.className += ' partlynew';
if (console)
console.info('partlynew ', link, '; cache=', cache, ' frag=', frag);
} else {
var entry = queue[title.getPrefixedText()];
if (!entry) {
entry = queue[title.getPrefixedText()] = [];
fresh.push(title.getPrefixedText());
}
entry.push(link);
}
} catch (e) {
if (window.console)
console.error(e, 'while processing', link, ' href=', link.href);
}
}
function processQueue(queue) {
function collect(sl) {
return jQuery.Deferred(function (d) {
var query = {
'action': 'query',
'titles': sl.join('|'),
'redirects': 1,
'prop': 'categories',
'cllimit': 100,
'continue': ''
};
var data;
function pluckResults(result) {
if (console)
console.info('result', result);
for (var pageid in result.query.pages) {
var titl = (new mw.Title(result.query.pages[pageid].title)).getPrefixedText();
var cats = result.query.pages[pageid].categories || [];
var cache = catcache[titl];
if (!cache)
cache = catcache[titl] = [];
for (var i = 0; i < cats.length; ++i) {
cache.push(cats[i].title.replace(/^Category:/, ''));
}
if (console)
console.info('cache for', titl, 'is', cache);
}
if (result.query.redirects) {
var redr = result.query.redirects;
for (var j = 0; j < redr.length; ++j) {
var fromt = (new mw.Title(redr[j].from)).getPrefixedText();
var targt = (new mw.Title(redr[j].to)).getPrefixedText();
catcache[fromt] = catcache[targt];
}
}
if (result['continue']) {
for (var key in result['continue'])
query[key] = result['continue'][key];
api.get(query).then(pluckResults, fail);
} else
d.resolve(sl);
}
function fail(code, details, xhr) {
d.reject(code, details, xhr);
}
api.get(query).then(pluckResults, fail);
});
}
for (var i = 0; i < fresh.length; i += 25) {
collect(fresh.slice(i, i + 25)).then(function (slice) {
for (var i = 0; i < slice.length; ++i) {
var links = queue[slice[i]];
for (var j = 0; j < links.length; ++j) {
processLink(links[j]);
}
delete queue[slice[i]];
}
}, function (code, details, xhr) {
console.error(code, details, xhr);
});
}
fresh = [];
}
var links = document.getElementsByTagName('a');
for (var i = 0; i < links.length; ++i) {
processLink(links[i]);
}
processQueue(queue);
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
if (mw.util.getParamValue('@orangelinks.no_live'))
MutationObserver = null;
if (MutationObserver) {
var mo = new MutationObserver(function (events) {
for (var i = 0; i < events.length; ++i) {
if (events[i].type === 'childList') {
for (var j = 0; j < events[i].addedNodes.length; ++j) {
if (events[i].addedNodes[j].tagName === 'A')
processLink(events[i].addedNodes[j]);
if (!events[i].addedNodes[j].getElementsByTagName)
continue;
var links = events[i].addedNodes[j].getElementsByTagName('a');
for (var k = 0; k < links.length; ++k) {
processLink(links[k]);
}
}
}
if ((events[i].type === 'attributes') && (events[i].target.tagName === 'A') && (events[i].attributeName === 'href')) {
processLink(events[i].target);
} else if ((events[i].type === 'attributes') && (events[i].target.tagName === 'A') && (events[i].attributeName === 'class')) {
processLink(events[i].target);
}
}
processQueue(queue);
});
mo.observe(document, {
attributes: true,
childList: true,
subtree: true
});
}
})();