MediaWiki:Gadget-problemy-w-odn.js
Uwaga: aby zobaczyć zmiany po opublikowaniu, może zajść potrzeba wyczyszczenia pamięci podręcznej przeglądarki.
- Firefox / Safari: Przytrzymaj Shift podczas klikania Odśwież bieżącą stronę, lub naciśnij klawisze Ctrl+F5, lub Ctrl+R (⌘-R na komputerze Mac)
- Google Chrome: Naciśnij Ctrl-Shift-R (⌘-Shift-R na komputerze Mac)
- Edge: Przytrzymaj Ctrl, jednocześnie klikając Odśwież, lub naciśnij klawisze Ctrl+F5.
- Opera: Naciśnij klawisze Ctrl+F5.
/**
* <nowiki>
* Skrypt zaznacza linki do kotwic, które nie istnieją na aktualnie odwiedzanej stronie.
* Zaznacza również elementy bibliografii, które nie zostały podlinkowane z użyciem {{odn}}.
* Nie sprawdza linków do innych stron.
*
* @author [[w:pl:User:Msz2001]]
*/
$(function(){
/**
* Returns an URL without the fragment part.
* @param {string} url The URL
* @returns {string}
*/
function stripFragmentFromUrl(url){
if(url.indexOf('#') > -1){
url = url.substring(0, url.indexOf('#'));
}
return url;
}
/**
* Normalizes an element id to be safe for comparison with fragment taken from URL.
* @param {string} id The element's id
* @returns {string}
*/
function normalizeId(id){
return '#' + id.replace(/%25/g, '%')
}
/**
* Adds a passed string to the element's title
* @param {HTMLElement} element An element to add to the title
* @param {string} newTitle A new portion of the title
*/
function addToTitle(element, newTitle){
if(element.title){
element.title += ' – ' + newTitle;
} else {
element.title = newTitle;
}
}
/**
* Returns a list of anchor ids that are present on the page.
* @returns {string[]}
*/
function listValidAnchorTargets(){
var elementsWithId = Array.from(document.querySelectorAll('.mw-parser-output [id]'));
var ids = elementsWithId.map(function(element){
// Prepended with hash to match HTMLAnchorElement.hash property
// Sometimes MediaWiki escapes % to %25 in id, so we need to replace it back
return normalizeId(element.id);
});
return ids;
}
/**
* Returns a list of links that point to the current page.
* @returns {HTMLAnchorElement[]}
*/
function listLinksToSelf(){
var currentUrl = stripFragmentFromUrl(window.location.href);
var links = Array.from(document.querySelectorAll('.mw-parser-output a[href^="#"]'));
links = links.filter(function(link){
return stripFragmentFromUrl(link.href) === currentUrl;
});
return links;
}
/**
* Iterates over the links and checks if the target anchor exists on the page.
* @param {HTMLAnchorElement[]} links The links to check
* @param {string[]} validAnchors The valid target anchor ids
*/
function markInvalidLinks(links, validAnchors){
links.forEach(function(link){
if(link.hash === '') return;
var target = decodeURIComponent(link.hash);
if(validAnchors.indexOf(target) === -1){
link.classList.add('missing-anchor');
addToTitle(link, 'Link do nieistniejącej kotwicy');
}
});
}
/**
* Returns a list of citations on the page
* @returns {HTMLElement[]}
*/
function listCitationsThatShouldBeLinked(){
// Include all the citations with an id
var include = Array.from(document.querySelectorAll('.mw-parser-output cite.citation[id]'));
// But exclude those in the reference list as they are already linked from the content
var exclude = Array.from(document.querySelectorAll('.mw-parser-output .references cite.citation[id]'));
return include.filter(function(citation){
return !exclude.includes(citation);
});
}
/**
* Marks elements that are not linked to (using #anchor links)
* @param {HTMLElement[]} elements The elements to check
* @param {HTMLAnchorElement[]} links The links to check
*/
function markElementsWithNoLinkTo(elements, links){
elements.forEach(function(element){
var id = normalizeId(element.id);
var linkExists = links.some(function(link){
var target = decodeURIComponent(link.hash);
return target === id;
});
if(!linkExists){
element.classList.add('missing-anchor');
addToTitle(element, 'Brak linku do tej pozycji w tekście');
}
});
}
/**
* Marks all the elements that have duplicate ids.
*/
function markElementsWithDuplicateIds(){
var elements = Array.from(document.querySelectorAll('.mw-parser-output [id]'));
var ids = elements.map(function(element){
return element.id;
});
var idCount = {};
ids.forEach(function(id){
idCount[id] = (idCount[id] || 0) + 1;
});
elements.forEach(function(element){
if (idCount[element.id] <= 1) return;
element.classList.add('duplicate-id');
addToTitle(element, 'Identyfikator występuje więcej niż raz na stronie (#' + element.id + ')');
});
}
var validAnchors = listValidAnchorTargets();
var linksToSelf = listLinksToSelf();
markInvalidLinks(linksToSelf, validAnchors);
var citations = listCitationsThatShouldBeLinked();
markElementsWithNoLinkTo(citations, linksToSelf);
// Flow produces a ton of duplicate ids, so we skip checking them if Flow is enabled
// Hopefully, in early 2025, Flow will be disabled and this check can be dropped
if (mw.config.get('wgFlowData') === null)
markElementsWithDuplicateIds();
mw.util.addCSS('@media screen {' +
'.missing-anchor { background-color: #fcc; }' +
'.duplicate-id { background-color: #fdeec1; outline: 1px solid #c80; }' +
'html.enable-dark-skin .missing-anchor, html.skin-theme-clientpref-night .missing-anchor { background-color: #514a16; }' +
'html.enable-dark-skin .duplicate-id, html.skin-theme-clientpref-night .duplicate-id { background-color: #4f3f0e; }' +
'}\n@media screen and (prefers-color-scheme: dark) {' +
'html.skin-theme-clientpref-os .missing-anchor { background-color: #514a16; }' +
'html.skin-theme-clientpref-os .duplicate-id { background-color: #4f3f0e; }' +
'}'
);
});
// </nowiki>