User:Polygnotus/DuplicateReferences.js: Difference between revisions

Content deleted Content added
No edit summary
No edit summary
Line 7:
let referencesHeading = document.getElementById("References");
if (!referencesHeading) {
console.log("References heading not found");
return;
}
Line 23 ⟶ 24:
newParagraph.style.color = "red";
function addDuplicateCitationsTemplate() {
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() {
const referencesList = document.querySelector('ol.references');
constif referenceItems = referencesList ? Array.from(!referencesList.children) : [];{
console.log("References list not found");
return [];
}
const referenceItems = Array.from(referencesList.children);
console.log("Number of reference items:", referenceItems.length);
const urlMap = new Map();
const duplicates = [];
Line 81 ⟶ 39:
const refNumber = index + 1;
const span = item.querySelector('span.reference-text');
if (!span) {
console.log("Reference text span not found for item", refNumber);
return;
}
const links = span.querySelectorAll('a');
 
Line 114 ⟶ 76:
});
 
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);
}
 
Line 184 ⟶ 84:
if (duplicateInfo.length > 0) {
if (documentconsole.querySelectorlog('table.box-Duplicated_citations')"Duplicates ===found, nullcreating list") {;
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 229 ⟶ 105:
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(', '));
Line 277 ⟶ 114:
});
console.log("Appending duplicate list to page");
parentDiv.after(newParagraph);
} else {
console.log("No duplicates found");
}
}
checkDuplicateReferenceLinks();
console.log("Script execution completed");
});
});