User:BrownHairedGirl/linkrot.js

// Linkrot.js v2.0 -- with untagging, and ref counting. 9 March 2022 // // Install with: // // or with //

// This script is hacked from User:DannyS712/Draft no cat.js // If forking this script, please note our contributions / give us credit

if ( mw.config.get( 'wgNamespaceNumber' ) === 0) { mw.loader.using( 'mediawiki.util', function {    $(document).ready( function  { var link = mw.util.addPortletLink( 'p-cactions', '#', 'Linkrot', 'ca-linkrot', 'Linkrot'); $( link ).click( function ( event ) {           event.preventDefault;            add_or_remove_linkrot_tag;        } ); } ); } ); }

// making these global variables global to avoid pssing them as parameters let CleanupBareURLsTagMatcher = /\{\{ *([tT]emplate *: *)?([Cc]leanup[_ ]+bare[_ ]+URLs|[Bb]are[_ ]+|[Bb]are|[Bb]are[_ ]+link|[Bb]are[_ ]+linkname|[Bb]are[_ ]+links|[Bb]are[_ ]+references|[Bb]are[_ ]+refs|[Bb]are[_ ]+URL|[Bb]are[_ ]+[uU][rR][[lL]s|[Bb]are-URLs|[Bb]arelinks|[Bb]areURL|[Bb]areURLs|[Cc]leanup[_ ]+bare-URLs|[Cc]leanup[_ ]+link[_ ]+rot|[Cc]leanup[_ ]+link-rot|[Cc]leanup-Bare[_ ]+URLs|[Cc]leanup-barelinks|[Cc]leanup-link[_ ]+rot|[Cc]leanup-link-rot|[Cc]leanup-linkrot|[Cc]UBURL|[Ll]ink[_ ]*rot|[Ll]INKROT|[Ll]R) *(\|[^\}]*)?\}\}\s*/g; var lkrArticleOriginalText = null; var lkrWgPageName = null;

function add_or_remove_linkrot_tag { let add_linkrot_edit_summary = "Added, " + "using a script. " + "For other recently-tagged pages with bare URLs, " + "see Category:Articles with bare URLs for citations from " + monthyear_datestamp + ""; let remove_linkrot_edit_summary = "Removed, " + "using a script. " + "This page currently has no Bare URLs";

var send_req = { action: 'query', titles: mw.config.get( 'wgPageName' ), prop: 'revisions', intoken: 'edit', rvprop: 'content', indexpageids: 1, dataType: 'xml', format: 'xml' };	lkrWgPageName = mw.config.get( 'wgPageName' ); $.get( mw.config.get( 'wgScriptPath' ) + '/api.php', send_req, function( response ) {	   lkrArticleOriginalText = $( response ).find( 'rev' ).text;		var lkrArticleNewText = null;		var lkr_edit_summary = null;		var myActionString = lkrPreCheck;		if ((myActionString) == null || (myActionString == "")) {			return; // no action		}		else if (myActionString == "addtag") {			lkrArticleNewText = "\n" + lkrArticleOriginalText;			lkr_edit_summary = add_linkrot_edit_summary;		}		else if (myActionString == "untag") {			lkrArticleNewText = lkrArticleOriginalText.replaceAll(CleanupBareURLsTagMatcher, '');			// check that removal worked			if (lkrArticleNewText == lkrArticleOriginalText) {				alert("ERROR\n\nTag removal failed");				return;			}			lkr_edit_summary = remove_linkrot_edit_summary;		}		// sanity check		if (!(lkr_edit_summary && lkrArticleNewText)) {			alert("ERROR!\n\naction failed: " + myActionString); return; }	   var submit = { action: 'edit', pageid: mw.config.get( 'wgArticleId' ), text: lkrArticleNewText, summary: lkr_edit_summary, minor: true, token: mw.user.tokens.get( 'csrfToken' ) };	   $.when(	        $.post( mw.config.get( 'wgScriptPath' ) + '/api.php', submit, function( response ){ } )	    ).done( function {	    	location.reload;	    } ); } ); }

function monthyear_datestamp { var d = new Date; let month = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

var myyear = d.getFullYear;

let mydatestamp = month[d.getMonth] + " " + myyear.toString; return mydatestamp; }

function lkrPreCheck { // Start by checking for an existing tag var CleanupBareURLsTagCount = lkrCountMatches(CleanupBareURLsTagMatcher);

// Now count bare URLs and tags var untaggedBareURLcount = lkrCountMatches(/]*?\>\s*\[?\s*https?:[^>< \|\[\]]+\s*\]?\s*<\s*\/\s*ref/gi); var BareURLinlineTagcount = lkrCountMatches(/\{\{ *([tT]emplate *: *)?([Bb]are[_ ]+URL[\- ]inline|[Ll]inkrot-inline|[Bb]are-inline|[Bb]are[_ ]+inline|[Bb]are[_ ]+url[_ ]+inline|[Bb]are-url[_ ]+inline|[Bb]are[_ ]+link[_ ]+inline|[Bb]are-link-inline|[Bb]are-url-inline|[Bb]are[_ ]+url) *(\|[^\}]*)?\}\}/g); var BareURLPDFTagcount = lkrCountMatches(/\{\{ *([tT]emplate *: *)?([Bb]are[_ ]+URL[\- ]PDF) *(\|[^\}]*)?\}\}/g); if (CleanupBareURLsTagCount > 0) { // Alreday tagged with if ((untaggedBareURLcount + BareURLinlineTagcount + BareURLPDFTagcount) == 0) { if (confirm("" + lkrWgPageName + " has no bare URL refs.\n\n" + toUnicodeVariant("Remove", 'bold') + " ?")) { return "untag"; }			else return null; }		else { // Already tagged alert("" + lkrWgPageName + " is already tagged with "); return null; }	}	else { // No existing tag if ((untaggedBareURLcount + BareURLinlineTagcount + BareURLPDFTagcount) == 0) { alert("" + lkrWgPageName + " has no bare URLs"); return null; }		else { // We have bare URLs var myTotalCountOfBareURLs = untaggedBareURLcount + BareURLinlineTagcount + BareURLPDFTagcount; var myTotalCountOfTaggedBareURLs = BareURLinlineTagcount + BareURLPDFTagcount; if (confirm("" + lkrWgPageName + " has " + myTotalCountOfBareURLs + " bare URLs:\n* " + myTotalCountOfTaggedBareURLs + " inline-tagged\n* " + untaggedBareURLcount + " untagged." + "\n\n" + toUnicodeVariant("Add", 'bold') + " the banner tag ?")) { return "addtag"; }			return null; }	}	return null; // we shouldn't be able to get here, but just in case ... }

function lkrCountMatches(myREgEx) { var count = 0; while (myREgEx.exec(lkrArticleOriginalText) !== null) { ++count; }	return count; }

/** * (c) David Konrad 2018 * MIT License * * Javascript function to convert plain text to unicode variants * * Loosely based on the nodejs monotext CLI utility https://github.com/cpsdqs/monotext * (c) cpsdqs 2016 * * For more inspiration see http://unicode.org/charts/ * */

/* * supported unicode variants * * m: monospace * b: bold * i: italic * c: script * g: gothic / fraktur * d: double-struck * s: sans-serif * o: circled text * p: parenthesized latin letters * w: fullwidth */

function toUnicodeVariant(str, variant, flags) {

const offsets = { m: [0x1d670, 0x1d7f6], b: [0x1d400, 0x1d7ce], i: [0x1d434, 0x00030], bi: [0x1d468, 0x00030], c: [0x1d49c, 0x00030], bc: [0x1d4d0, 0x00030], g: [0x1d504, 0x00030], d: [0x1d538, 0x1d7d8], bg: [0x1d56c, 0x00030], s: [0x1d5a0, 0x1d7e2], bs: [0x1d5d4, 0x1d7ec], is: [0x1d608, 0x00030], bis: [0x1d63c, 0x00030], o: [0x24B6, 0x2460], p: [0x249C, 0x2474], w: [0xff21, 0xff10], u: [0x2090, 0xff10] };

const variantOffsets = { 'monospace': 'm', 'bold' : 'b', 'italic' : 'i', 'bold italic' : 'bi', 'script': 'c', 'bold script': 'bc', 'gothic': 'g', 'gothic bold': 'bg', 'doublestruck': 'd', 'sans': 's', 'bold sans' : 'bs', 'italic sans': 'is', 'bold italic sans': 'bis', 'parenthesis': 'p', 'circled': 'o', 'fullwidth': 'w'	};

// special characters (absolute values) var special = { m: { ' ': 0x2000, '-': 0x2013 },	 i: { 'h': 0x210e },	 g: { 'C': 0x212d, 'H': 0x210c, 'I': 0x2111, 'R': 0x211c, 'Z': 0x2128 },		o: { '0': 0x24EA, '1': 0x2460, '2': 0x2461, '3': 0x2462, '4': 0x2463, '5': 0x2464, '6': 0x2465, '7': 0x2466, '8': 0x2467, '9': 0x2468, },		p: {}, w: {} };	//support for parenthesized latin letters small cases for (var i = 97; i <= 122; i++) { special.p[String.fromCharCode(i)] = 0x249C + (i-97); }	//support for full width latin letters small cases for (var iz = 97; iz <= 122; iz++) { special.w[String.fromCharCode(iz)] = 0xff41 + (iz-97); }

const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; const numbers = '0123456789';

var getType = function(variant) { if (variantOffsets[variant]) return variantOffsets[variant]; if (offsets[variant]) return variant; return 'm'; //monospace as default };	var getFlag = function(flag, flags) { if (!flags) return false; return flags.split(',').indexOf(flag)>-1; };

var type = getType(variant); var underline = getFlag('underline', flags); var strike = getFlag('strike', flags); var result = '';

for (var k of str) { let index; let c = k;   if (special[type] && special[type][c]) c = String.fromCodePoint(special[type][c]); if (type && (index = chars.indexOf(c)) > -1) { result += String.fromCodePoint(index + offsets[type][0]); } else if (type && (index = numbers.indexOf(c)) > -1) { result += String.fromCodePoint(index + offsets[type][1]); } else { result += c;   } if (underline) result += '\u0332'; // add combining underline if (strike) result += '\u0336'; // add combining strike }	return result }