User:Chew/Scripts/PasteArchiveInfo.js: Difference between revisions

Content deleted Content added
initial archive helper script
 
support archive.today, clean up code, fix bug with inconsistent pasting in wrong element
 
(One intermediate revision by one other user not shown)
Line 1:
class VisualEditorParameter {
document.addEventListener('paste', function(event) {
element;
const pastedInput = event.target;
 
constructor(el) {
// Ensure the paste is happening in an input element
this.element = el;
if (pastedInput.tagName.toLowerCase() !== 'input') {
}
return;
}
 
get name() {
// Get the pasted text from the clipboard
// get first child, its first child, and the innerText
let pastedText = (event.clipboardData || window.clipboardData).getData('text');
return this.element.children[0].children[0].textContent ?? '';
}
 
setValue(val) {
// Ensure the pasted text is a "web.archive.org" link
// set value of the input element
if (!pastedText.startsWith('https://web.archive.org/web/')) {
const el = this.element.children[2].children[0].children[0];
console.error('Pasted text is not a web.archive.org link.');
if (el.value.toString().length === 0) {
return; // Exit if it's not a valid Web Archive URL
el.value = val;
}
}
 
focus() {
// Remove "https://web.archive.org/web/{14-digit-timestamp}/" part from the URL
// focus the input element
const newUrl = pastedText.replace(/https:\/\/web\.archive\.org\/web\/\d{14}\//, '');
const el = this.element.children[2].children[0].children[0];
el.focus();
}
}
 
/**
* Finds a parameter by name in the given parameters array.
* @param {VisualEditorParameter[]} params the list of params
* @param {string} name the name of the parameter to find
* @return {VisualEditorParameter | undefined} the parameter with the given name, or null if not found
*/
function findParam(params, name) {
// find the parameter with the given name
return params.find((param) => param.name === name);
}
 
document.addEventListener('paste', (event) => {
const pastedInput = event.target;
 
if (!pastedInput) {
return;
}
 
// Ensure the paste is happening in an input element
if (!(pastedInput instanceof HTMLInputElement)) {
console.log('Pasted input is not an HTMLInputElement.');
return;
}
 
// Get the pasted text from the clipboard
const pastedText = event.clipboardData?.getData('text/plain') || '';
 
let date = '';
let url = '';
 
// Ensure the pasted text is a "web.archive.org" link
if (pastedText.startsWith('https://web.archive.org/web/')) {
url = pastedText.replace(/https:\/\/web\.archive\.org\/web\/\d{14}\//, '');
const timestampMatch = /https:\/\/web\.archive\.org\/web\/(\d{14})\//.exec(pastedText);
 
// Extract the 14-digit timestamp from the Web Archive URL
const timestampMatch = pastedText.match(/https:\/\/web\.archive\.org\/web\/(\d{14})\//);
let dateISO = "";
if (timestampMatch) {
const timestamp = timestampMatch[1]; // Get the timestamp (14 digits)
const year = timestamp.substring(0, 4);
const month = timestamp.substring(4, 6);
const day = timestamp.substring(6, 8);
// Create the YYYY-MM-DD date string
dateISO = `${year}-${month}-${day}`;
}
 
if (!timestamp) {
// Traverse up to find the label, handling missing elements gracefully
try { return;
}
const pastedBox = pastedInput.parentElement
.parentElement.parentElement.children[0].children[0];
 
const year = timestamp.slice(0, 4);
// Ensure 'pastedBox' exists and is a label with the correct text
const month = timestamp.slice(4, 6);
if (!pastedBox || pastedBox.tagName.toLowerCase() !== 'label' || pastedBox.innerText !== "Archive URL") {
const day = timestamp.slice(6, 8);
console.error('Label check failed or not "Archive URL".');
return; // Exit if the label is not "Archive URL" or traversal failed
}
 
// Create the YYYY-MM-DD date string
} catch (err) {
date = `${year}-${month}-${day}`;
console.error('Error during DOM traversal for label check:', err);
return; // Exit if there's an error in the traversal process
}
} else if (
pastedText.startsWith('https://archive.today/') ||
pastedText.startsWith('http://archive.today/')
) {
// must match http://archive.today/2013.08.02-201601/url_to_use
url = pastedText.replace(/https?:\/\/archive\.today\/\d{4}\.\d{2}\.\d{2}-\d{6}\//, '');
 
const timestampMatch = /https?:\/\/archive\.today\/(\d{4}\.\d{2}\.\d{2})-\d{6}\//.exec(
// Simplify the repetitive DOM access to a single constant
pastedText,
const formInputs = pastedInput.parentElement.parentElement.parentElement.parentElement;
);
 
tryif (timestampMatch) {
date = timestampMatch[1].replaceAll('.', '-'); // Get the date (YYYY.MM.DD)
// Check if the URL input is empty before pasting
} else {
const urlInput = formInputs.children[6].children[2].children[0].children[0];
console.error('Invalid date format in archive.today URL.');
if (!urlInput.value) {
urlInput.value = newUrlreturn; // OnlyExit pasteif the new URL if thedate inputformat is emptyinvalid
}
 
// Check if the date input is empty before pasting the extracted date
const dateInput = formInputs.children[9].children[2].children[0].children[0];
if (!dateInput.value) {
dateInput.value = dateISO; // Only paste the date if the input is empty
}
} catch (err) {
console.error('Error traversing the DOM or setting value:', err);
}
} else {
console.error('Pasted text is not a web.archive.org nor archive.today link.');
return; // Exit if it's not a valid Web Archive URL
}
 
const parameters = Array.from(document.querySelectorAll('.ve-ui-mwParameterPage')).map(
(el) => new VisualEditorParameter(el),
);
 
// Simplify the repetitive DOM access to a single constant
const urlInput = findParam(parameters, 'URL');
const archiveUrl = findParam(parameters, 'Archive URL');
const archiveDate = findParam(parameters, 'Archive date');
 
if (urlInput) {
urlInput.setValue(url);
setTimeout(() => {
urlInput.focus();
}, 50);
} else {
console.error('URL parameter not found.');
}
 
if (archiveDate) {
archiveDate.setValue(date);
setTimeout(() => {
archiveDate.focus();
}, 100);
} else {
console.error('Archive Date parameter not found.');
}
 
setTimeout(() => {
archiveUrl.focus();
}, 200);
});