Content deleted Content added
Polygnotus (talk | contribs) No edit summary |
Polygnotus (talk | contribs) No edit summary |
||
Line 1:
mw.loader.using(['mediawiki.util'], function () {
$(document).ready(function () {
console.log("Script started");
if ((mw.config.get('wgNamespaceNumber') !== 0 && mw.config.get('wgPageName') !== 'User:Polygnotus/dupreftest') || mw.config.get('wgAction') !== 'view') {
console.log("Not the correct page or action, script terminated");
return;
}
Line 7 ⟶ 10:
let referencesHeading = document.getElementById("References");
if (!referencesHeading) {
console.log("References heading not found, script terminated");
return;
}
Line 24 ⟶ 27:
newParagraph.style.color = "red";
function addDuplicateCitationsTemplate() {
console.log("Adding duplicate citations template");
var api = new mw.Api();
var pageTitle = mw.config.get('wgPageName');
let duplicateInfo = getDuplicateInfo();
api.get({
action: 'query',
prop: 'revisions',
titles: pageTitle,
rvprop: 'content',
rvslots: 'main',
formatversion: 2
}).then(function(data) {
var page = data.query.pages[0];
var content = page.revisions[0].slots.main.content;
// Add the template at the top of the page
var newContent = '{{Duplicate citations}}\n' + content;
// Create the edit summary.
let summary = '+{{Duplicate citations}}';
if (duplicateInfo.length > 0) {
summary += ': ';
duplicateInfo.forEach((info, index) => {
summary += `${info.url} (refs: ${info.refs.join(', ')})`;
if (index < duplicateInfo.length - 1) {
summary += '; ';
}
});
}
// Make the edit
return api.postWithToken('csrf', {
action: 'edit',
title: pageTitle,
text: newContent,
summary: summary
});
}).then(function() {
mw.notify('Successfully added the Duplicate citations template!');
// Reload the page to show the changes
___location.reload();
}).catch(function(error) {
console.error('Error:', error);
mw.notify('Failed to add the template. See console for details.', {type: 'error'});
});
}
function getDuplicateInfo() {
console.log("Getting duplicate info");
const referencesList = document.querySelector('ol.references');
if (!referencesList) {
Line 78 ⟶ 132:
console.log("Number of duplicate sets found:", duplicates.length);
return duplicates;
}
function calculateSimilarity(str1, str2) {
const longer = str1.length > str2.length ? str1 : str2;
const shorter = str1.length > str2.length ? str2 : str1;
const longerLength = longer.length;
if (longerLength === 0) {
return 1.0;
}
return (longerLength - editDistance(longer, shorter)) / parseFloat(longerLength);
}
function editDistance(s1, s2) {
s1 = s1.toLowerCase();
s2 = s2.toLowerCase();
const costs = new Array();
for (let i = 0; i <= s1.length; i++) {
let lastValue = i;
for (let j = 0; j <= s2.length; j++) {
if (i == 0)
costs[j] = j;
else {
if (j > 0) {
let newValue = costs[j - 1];
if (s1.charAt(i - 1) != s2.charAt(j - 1))
newValue = Math.min(Math.min(newValue, lastValue),
costs[j]) + 1;
costs[j - 1] = lastValue;
lastValue = newValue;
}
}
}
if (i > 0)
costs[s2.length] = lastValue;
}
return costs[s2.length];
}
function getAllVisibleText(element) {
if (element.nodeType === Node.TEXT_NODE) {
return element.textContent.trim();
}
if (element.nodeType === Node.ELEMENT_NODE) {
if (window.getComputedStyle(element).display === 'none') {
return '';
}
return Array.from(element.childNodes)
.map(child => getAllVisibleText(child))
.join(' ')
.replace(/\s+/g, ' ')
.trim();
}
return '';
}
function extractVisibleText(htmlString) {
const parser = new DOMParser();
const doc = parser.parseFromString(htmlString, 'text/html');
return getAllVisibleText(doc.body);
}
function checkDuplicateReferenceLinks() {
console.log("Checking for duplicate reference links");
const duplicateInfo = getDuplicateInfo();
if (duplicateInfo.length > 0) {
console.log("Duplicates found, creating list");
if (document.querySelector('table.box-Duplicated_citations') === null) {
const editSections = parentDiv.querySelectorAll('span.mw-editsection');
editSections.forEach(editSection => {
let spanBefore = document.createElement('span');
spanBefore.className = 'mw-editsection-bracket';
spanBefore.textContent = '[';
let addTemplateLink = document.createElement('a');
addTemplateLink.textContent = ' add {{duplicated citations}} ';
addTemplateLink.href = '#';
addTemplateLink.addEventListener('click', function(e) {
e.preventDefault();
addDuplicateCitationsTemplate();
});
let spanAfter = document.createElement('span');
spanAfter.className = 'mw-editsection-bracket';
spanAfter.textContent = ']';
editSection.appendChild(spanBefore);
editSection.appendChild(addTemplateLink);
editSection.appendChild(spanAfter);
});
}
duplicateInfo.forEach(({ url, refs }) => {
Line 105 ⟶ 249:
paragraphInfo.appendChild(link);
// Highlight only the specific duplicates on hover
link.addEventListener('mouseover', () => {
refs.forEach(ref => {
const citationElement = document.getElementById(`cite_note-${ref}`);
if (citationElement) {
if (ref === refNumber) {
citationElement.classList.add('duplicate-citation-hover');
} else {
citationElement.classList.add('duplicate-citation-highlight');
}
}
});
});
link.addEventListener('mouseout', () => {
refs.forEach(ref => {
const citationElement = document.getElementById(`cite_note-${ref}`);
if (citationElement) {
citationElement.classList.remove('duplicate-citation-hover');
citationElement.classList.remove('duplicate-citation-highlight');
}
});
});
// Highlight duplicates on click and allow navigation
link.addEventListener('click', () => {
// Remove previous click highlights
document.querySelectorAll('.duplicate-citation-clicked').forEach(el => {
el.classList.remove('duplicate-citation-clicked');
});
// Add new click highlights
refs.forEach(ref => {
const citationElement = document.getElementById(`cite_note-${ref}`);
if (citationElement) {
citationElement.classList.add('duplicate-citation-clicked');
}
});
// The default behavior (navigation) will now occur
});
if (index < refs.length - 1) {
paragraphInfo.appendChild(document.createTextNode(', '));
|