User:DreamRimmer/BEFORE.js

//

$(function {	class NPPLinks {		/** add NPP, Earwig, WP:BEFORE, CSE, Wikipedia duplicate page links to left menu */		execute {			this._setVariables;			this._decideIfWeShouldUseLessLinks;			this._setURIVariables(this.pageName, this.namespace);			// this._debugURIVariables;			this._setURLVariables;			this._checkForArticlesInOtherLanguages;			this._checkForForeignCharacters;			// this._debugForeignCharacterDetection;			this._generateLinks;			this._insertHTML;		}

// TODO: convert to mw.util.addPortlet once https://phabricator.wikimedia.org/T303488 is completed _insertHTML { let menuTitle = 'New page patrol'; let html = ''; let skin = mw.config.get('skin'); switch ( skin ) { case 'minerva': // TODO: insert into the "More" menu, rather than the hamburger

html = `  ${this.links} `;

html = html.replace(//g, ''); html = html.replace(/(]*>)/g, '$1 '); html = html.replace(/<\/a>/g, ' ');

$('#p-navigation').after(html); break; case 'monobook': html = `   ${menuTitle}  ${this.links}  `;					$('#p-navigation').after(html); break; case 'modern': html = `  ${menuTitle} ${this.links}  `;					$('#p-navigation').after(html); break; case 'timeless': html = `  ${menuTitle} ${this.links}  `;					$('#p-navigation').after(html); break; case 'vector-2022': html = `  ${menuTitle}  ${this.links} </ul> `;					$('#p-navigation').after(html); break; case 'vector': default: html = ` <nav id="p-npp-links" class="mw-portlet mw-portlet-npp-links vector-menu vector-menu-portal portal" aria-labelledby="p-npp-links-label" role="npp-links"> <h3 id="p-npp-links-label" class="vector-menu-heading"> ${menuTitle} <ul class="vector-menu-content-list"> ${this.links} </ul> `;					$('#p-navigation').after(html); break; }		}

_generateLinks { // always display a link to Special:NewPagesFeed this.links += `<li><a href="/wiki/Special:NewPagesFeed">New pages feed</a></li>`;

// if on a page where NPPLinks should run (mainspace), display all the links, so the person can do WP:BEFORE if ( ! this.lessLinks ) { this.links += ` <li><a href="${this.rottentomatoesSearchURL}" ${this.sameTab}>Rotten Tomatoes</a></li> <li><a href="${this.reviewSearchURL}" ${this.sameTab}>Film Reviews</a></li> <li><a href="${this.copyvioURL}" ${this.sameTab}>Copyvio check</a></li> <li><a href="${this.wikipediaDuplicateCheckURL}" ${this.sameTab}>Duplicate article check</a></li> <li><a href="https://gptzero.me/" ${this.sameTab}>AI/LLM check</a></li> <li><a href="${this.webSearchURL}" ${this.sameTab}>WP:BEFORE web</a></li> <li><a href="${this.newsSearchURL}" ${this.sameTab}>WP:BEFORE news</a></li> <li><a href="${this.oldNewsSearchURL}" ${this.sameTab}>WP:BEFORE news archive</a></li> <li><a href="${this.bookSearchURL}" ${this.sameTab}>WP:BEFORE books</a></li> <li><a href="${this.journalSearchURL}" ${this.sameTab}>WP:BEFORE scholar</a></li> ${this.messages} <li><a href="${this.profileSearchURL}" ${this.sameTab}>Professor (Google)</a></li> <li><a href="${this.profileSearchURL2}" ${this.sameTab}>Professor (Scopus)</a></li> <li><a href="${this.cseSearchURL}" ${this.sameTab}>Reliable sources search</a></li> <li><a href="${this.newsInTitleSearchURL}" ${this.sameTab}>News (name in title)</a></li> <li><a href="${this.wikidataSearchURL}" ${this.sameTab}>Wikidata</a></li> <li><a href="${this.catalogueOfLifeSearchURL}" ${this.sameTab}>Species search</a></li> `;

// TODO: purge page, so orphan count is correct // TODO: display message if orphan // TODO: display message if no categories }		}

_checkForForeignCharacters { // WP:BEFORE foreign script search this.articleBody = $('#mw-content-text').html; this.articleBody = this.articleBody.replace(/(<([^>]+)>)/gi, ''); // remove HTML tags this.articleBody = this.articleBody.trim.split('Contents')[0]; // lead only. trim everything after the word "Contents" (table of contents) let regEx = new RegExp(`^[${this.listOfNonForeignCharacters}]*$`, ''); let ansiOnly = regEx.test(this.articleBody); // the ones at the end are vietnamese if ( ! ansiOnly ) { // Use an <a> tag with CSS to turn off the hyperlink. This is so that Minerva skin works correctly. Minerva always expects an <a> tag. this.messages += `<li><a style="pointer-events: none; cursor: default; color:black;">WP:BEFORE search for foreign name</a></li>\n`; }		}		_checkForArticlesInOtherLanguages { // WP:BEFORE wikis in other languages if ( $('#p-lang li').length ) { // Use an <a> tag with CSS to turn off the hyperlink. This is so that Minerva skin works correctly. Minerva always expects an <a> tag. this.messages += `<li><a style="pointer-events: none; cursor: default; color:black;">WP:BEFORE check foreign wikis</a></li>\n`; }		}

_setURLVariables { this.rottentomatoesSearchURL = `https://www.rottentomatoes.com/search?search=${this.underscores}`; this.reviewSearchURL = `https://www.google.com/search?q=${this.quotedNoUnderscores}+film reviews`; this.copyvioURL = `https://copyvios.toolforge.org/?lang=en&project=wikipedia&title=${this.underscores}`; this.webSearchURL = `https://www.google.com/search?q=${this.quotedNoUnderscores}+-wikipedia.org`; this.bookSearchURL = `https://www.google.com/search?q=${this.quotedNoUnderscores}&tbm=bks`; this.newsSearchURL = `https://www.google.com/search?q=${this.quotedNoUnderscores}&tbm=nws`; this.newsInTitleSearchURL = `https://www.google.com/search?q=intitle:${this.quotedNoUnderscores}&tbm=nws`; this.oldNewsSearchURL = `https://www.google.com/search?tbm=bks&tbs=bkt:s&source=newspapers&q=${this.quotedNoUnderscores}`; this.journalSearchURL = `https://scholar.google.com/scholar?q=${this.quotedNoUnderscores}`; this.profileSearchURL = `https://www.google.com/search?q=${this.noUnderscoresNoParentheses}%20%22h-index%22`; this.profileSearchURL2 = `https://www.scopus.com/results/authorNamesList.uri?st1=${this.lastName}&st2=${this.firstName}`; this.cseSearchURL = `https://cse.google.com/cse?cx=007734830908295939403:galkqgoksq0&q=${this.quotedNoUnderscores}`; this.wikipediaDuplicateCheckURL = `https://en.wikipedia.org/w/index.php?search=${this.noUnderscores}&title=Special:Search&profile=advanced&fulltext=1&advancedSearch-current=%7B%7D&ns0=1`; this.wikidataSearchURL = `https://www.wikidata.org/w/index.php?search=${this.quotedNoParentheses}&title=Special%3ASearch&go=Go&ns0=1&ns120=1`; this.catalogueOfLifeSearchURL = `https://www.catalogueoflife.org/data/search?facet=rank&facet=issue&facet=status&facet=nomStatus&facet=nameType&facet=field&facet=authorship&facet=extinct&facet=environment&limit=50&offset=0&q=${this.noUnderscores}&sortBy=taxonomic`; }

_setVariables { // This is a preference the user can set in their common.js			// @ts-ignore this.sameTab = window.NPPLinksSameTab ? '' : 'target="_blank"';

// Here's some commonly used variables this.namespace = mw.config.get('wgNamespaceNumber'); this.pageName = mw.config.get('wgPageName'); // has underscores instead of spaces. has namespace prefix this.listOfNonForeignCharacters = `\u0000-\u036f\ua792\u200b\u2009\u2061\u200e–—−▶◀•←†↓√≠≈→⋯’\u0020-\u002F\u0030-\u0039\u003A-\u0040\u0041-\u005A\u005B-\u0060\u0061-\u007A\u007B-\u007E\u00C0-\u00C3\u00C8-\u00CA\u00CC-\u00CD\u00D0\u00D2-\u00D5\u00D9-\u00DA\u00DD\u00E0-\u00E3\u00E8-\u00EA\u00EC-\u00ED\u00F2-\u00F5\u00F9-\u00FA\u00FD\u0102-\u0103\u0110-\u0111\u0128-\u0129\u0168-\u0169\u01A0-\u01B0\u1EA0-\u1EF9\u02C6-\u0323`; this.messages = ''; this.links = ''; }

/** Prints to console a list of foreign characters detected. Any characters in this list that aren't foreign characters, such as unicode whitespace characters or unicode symbols that aren't language-related, are bugs. The fix is to add them to the RegEx as an exception. */		_debugForeignCharacterDetection { console.log(this.articleBody); let regEx = new RegExp(`[^${this.listOfNonForeignCharacters}]`, 'g'); let matches = this.articleBody.match(regEx); if ( matches ) { for ( let match of matches ) { console.log(match); console.log(match.charCodeAt(0)); }			}		}

_decideIfWeShouldUseLessLinks { // only include most links for action = view and namespace = main, draft let action = mw.config.get('wgAction'); let desiredNamespace = [0, 118].includes(this.namespace); this.lessLinks = false; if ( action !== 'view' || ! desiredNamespace ) { this.lessLinks = true; }			let isAFD = this.pageName.startsWith('Wikipedia:Articles_for_deletion/'); if ( isAFD ) { this.lessLinks = false; this.pageName = this.pageName.replace('Wikipedia:Articles_for_deletion/', ''); }		}

_debugURIVariables { console.log(this.underscores); console.log(this.pageNameNoNamespace); console.log(this.quotedName); console.log(this.quotedNoParentheses); console.log(this.quotedNoUnderscores); console.log(this.noUnderscores); console.log(this.quotedNoUnderscoresNoParentheses); console.log(this.noUnderscoresNoParentheses); }		/** pageName has namespace, undescores, no quotes, parentheses */ _buildURIComponent(			wgPageName,			wgNamespaceNumber,			keepNamespace,			keepUnderscores,			wrapInDoubleQuotes,			keepDisambiguator		) { let output = wgPageName; // The order of all of these is important, because of RegEx patterns. if ( ! keepNamespace && wgNamespaceNumber !== 0 ) output = output.replace(/^.+?:/, ''); if ( ! keepDisambiguator ) { let matches = output.match(/^(.*)_\((.+?)\)$/); if ( typeof matches !== 'undefined' && matches && matches[1] ) { output = matches[1]; }			}			if ( wrapInDoubleQuotes ) { // If there's parentheses on the right, put the parentheses on the outside of the quotes, and remove the characters, but not their inner text let matches = output.match(/^(.*)_\((.+?)\)$/); // if parentheses on the right if ( typeof matches !== 'undefined' && matches && matches[2] ) { output = '"' + matches[1] + '"_' + matches[2]; } else { output = '"' + output + '"'; }			}			if ( ! keepUnderscores ) { output = output.replace(/_/g, ' '); }			output = encodeURIComponent(output); return output; }

_setURIVariables(pageName, namespace) { // Draft:Andrew_Hill_(pharmacologist) this.underscores = this._buildURIComponent(pageName, namespace, true, true, false, true); // Andrew_Hill_(pharmacologist) this.pageNameNoNamespace = this._buildURIComponent(pageName, namespace, false, true, false, true); // "Andrew_Hill"_pharmacologist this.quotedName = this._buildURIComponent(pageName, namespace, false, true, true, true); // "Andrew_Hill" this.quotedNoParentheses = this._buildURIComponent(pageName, namespace, false, true, true, false); // "Andrew Hill" pharmacologist this.quotedNoUnderscores = this._buildURIComponent(pageName, namespace, false, false, true, true); // Andrew Hill (pharmacologist) this.noUnderscores = this._buildURIComponent(pageName, namespace, false, false, false, true); // "Andrew Hill" this.quotedNoUnderscoresNoParentheses = this._buildURIComponent(pageName, namespace, false, false, true, false); // Andrew Hill this.noUnderscoresNoParentheses = this._buildURIComponent(pageName, namespace, false, false, false, false); // Andrew this.firstName = this._getFirstName(pageName); // Hill this.lastName = this._getLastName(pageName); }

_getLastName(pageName) { // TODO: this can probably be refactored to use this._buildURIComponent to delete the underscores and disambiguators, then do the regex

// underscores to spaces pageName = pageName.replace('_', ' ');

// delete disambiguators, e.g. Andrew Hill (pharmacologist) -> Andrew Hill pageName = pageName.replace(/ \([^\)]+\)$/, '');

// RegEx test cases: https://regex101.com/r/PcmHrN/1 let match = pageName.match(/\s?(\S+)$/); if ( match && match[1] ) { // spaces, not underscores return encodeURIComponent(match[1]); }			return ''; }

_getFirstName(pageName) { // TODO: this can probably be refactored to use this._buildURIComponent to delete the underscores and disambiguators, then do the regex

// underscores to spaces pageName = pageName.replace('_', ' ');

// delete disambiguators, e.g. Andrew Hill (pharmacologist) -> Andrew Hill pageName = pageName.replace(/ \([^\)]+\)$/, '');

// RegEx test cases: https://regex101.com/r/imLZ0j/1 let match = pageName.match(/^(.*)\s\S+$/); if ( match && match[1] ) { // spaces, not underscores return encodeURIComponent(match[1]); }			return ''; }	}

$(function {		let nppl = new NPPLinks;		nppl.execute;	}); });

//