User:Polygnotus/DuplicateReferences.js: Difference between revisions

Content deleted Content added
No edit summary
No edit summary
Line 2:
$(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;
}
 
console.log("Page title:", document.title);
console.log("URL:", window.___location.href);
 
function findNextReflistDiv(element) {
let referencesHeading = document.getElementById("References");
let nextElement = element.nextElementSibling;
if (!referencesHeading) {
while (nextElement) {
if (nextElement.tagName.toLowerCase() === 'div' && nextElement.classList.contains('reflist')) {
return nextElement;
}
nextElement = nextElement.nextElementSibling;
}
return null;
}
 
const referencesHeader = document.querySelector("h2#References");
if (!referencesHeader) {
console.log("References heading not found, script terminated");
return;
}
 
const containerDiv = referencesHeader.closest("div");
if (!containerDiv) {
console.log("Container div not found, script terminated");
return;
}
 
const reflistDiv = findNextReflistDiv(containerDiv);
if (!reflistDiv) {
console.log("Reflist div not found, script terminated");
return;
}
 
const referencesList = reflistDiv.querySelector('ol.references');
if (!referencesList) {
console.log("ol.references not found within reflist div");
return;
}
 
const style = document.createElement('style');
style.textContent = `
Line 25 ⟶ 54:
`;
document.head.appendChild(style);
 
let parentDiv = referencesHeading.closest("div");
let newParagraph = document.createElement("p");
newParagraph.style.color = "red";
 
function addDuplicateCitationsTemplate() {
console.log("Adding duplicate citations template");
Line 48 ⟶ 76:
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) {
Line 63 ⟶ 89:
}
 
// Make the edit
return api.postWithToken('csrf', {
action: 'edit',
Line 72 ⟶ 97:
}).then(function() {
mw.notify('Successfully added the Duplicate citations template!');
// Reload the page to show the changes
___location.reload();
}).catch(function(error) {
Line 82 ⟶ 106:
function getDuplicateInfo() {
console.log("Getting duplicate info");
const referencesHeading = document.getElementById("References");
if (!referencesHeading) {
console.log("References heading not found");
return [];
}
console.log("References heading found:", referencesHeading.outerHTML);
let currentElement = referencesHeading.nextElementSibling;
console.log("Next element after References heading:", currentElement ? currentElement.outerHTML : "None");
if (!currentElement || !currentElement.classList.contains('mw-references-wrap')) {
console.log("References list (mw-references-wrap) not found after References heading");
return [];
}
console.log("References list found:", currentElement.outerHTML);
const referencesList = currentElement.querySelector('ol.references');
if (!referencesList) {
console.log("ol.references not found within mw-references-wrap");
return [];
}
const referenceItems = referencesList.querySelectorAll('li');
Line 112 ⟶ 114:
 
referenceItems.forEach((item, index) => {
const refNumber = index + 1; // This is the correct reference number
console.log(`Processing reference item ${refNumber}`);
const span = item.querySelector('span.reference-text');
Line 161 ⟶ 163:
console.log("Duplicate sets:", duplicates);
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 234 ⟶ 173:
if (document.querySelector('table.box-Duplicated_citations') === null) {
const editSections = parentDivcontainerDiv.querySelectorAll('span.mw-editsection');
editSections.forEach(editSection => {
Line 278 ⟶ 217:
paragraphInfo.appendChild(link);
 
// Highlight only the specific duplicates on hover
link.addEventListener('mouseover', () => {
refs.forEach(ref => {
Line 301 ⟶ 239:
});
 
// 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}`);
Line 314 ⟶ 249:
}
});
// The default behavior (navigation) will now occur
});
Line 327 ⟶ 261:
console.log("Appending duplicate list to page");
parentDivcontainerDiv.after(newParagraph);
} else {
console.log("No duplicates found");