User:Moonythedwarf/extra-unreliable.js

// Instructions available at User:Moonythedwarf/extra-unreliable

// Feel free to request tweaks or additional sources to be covered on the talk page

// Adapted from https://en.wikipedia.org/w/index.php?title=Wikipedia:User_scripts/Requests&diff=939432100&oldid=939403363 by User:SD0001

// Updated from https://en.wikipedia.org/w/index.php?title=User:Jorm/unreliable.js&oldid=940556311 by User:Jorm

// Updated from https://en.wikipedia.org/w/index.php?title=User:SD0001/unreliabe.js&oldid=941114456 by User:SD0001

// Updated from https://en.wikipedia.org/w/index.php?title=User:SD0001/unreliable.js&action=edit by User:SD0001

// Updated from https://en.wikipedia.org/w/index.php?title=User:Creffett/unreliable.js&oldid=957395306 by User:Creffett

// Adapted from https://en.wikipedia.org/w/index.php?title=User:Headbomb/unreliable.js&oldid=987448454 by User:Headbomb

// Big thanks to various spam-fighters on and off wiki for helping provide resources to design the built-in regexes on.

//

// \/ regex in links doesn't work as it should, use (%2F|\/) instead

$( function() {

var rules = [

// Language 1

{

comment: 'Promotional phrasing',

// this regex kinda sucks

regex: /(?:\bextensive\s+(?:experience|work)|\bthe\s+field|\bwe|\bour|\ball\s+rights\s+reserved|\brevolutionary|\byour|\baward(?:\s+|\-)winning|\bperfect|\bthe\s+community|\bon\s+the\s+rise\s+|(?:\(tm\)|™)|\binspiration|\bhere\s+(?:at|in)|\bstrive|\bthe\s+best|\b(?:low|amazing|incredible|unbeatable)\s+(?:price|cost)(?:s?)|\bunbeatable|\b100%\s+guaranteed|\bwide\s+selection|\bbothersome|\b(?:wildly|amazingly|outstandingly|)\s+popular|\btoday|\btommorow|\bfrenzy|\baffordable|\bloved|\bwell(?:\s+|\-)known|\bfastest\s+growing|\bpost|\bexciting\s+(?:day|week|year|month)|\bexciting|\bendless|\bcustomers|\bhousehold\s+name|\byou|\bpublished\s+\d\s+(?:seconds|minutes|hours|days|months|years)\s+ago|\bgreatest|\bbest\s+ever|\bmilestone|\bin\s+the\s+world)\b/gmi,

css: { "background-color": "#ea985d" },

text_matcher: true,

},

// Language 2

{

comment: 'Promotional phrasing',

// more bad regex!

regex: /(?:\b(?:her|his)\s+(?:distinctive|powerful|unique|amazing|exceptional|exquisite|one\s+of\s+a\s+kind)\b|\b(?:explore|embracing|accepting|using|utilizing|creating|building)\s+ideas\b|\bnumerous|\bmore\s+than\b|\beffectively\s+(?:commit|turn|create|modify|sell)\b|\b(?:amazing|powerful|unique|exceptional|impressive)\s+technology\b|\bnew\s+standard\b|\bworld(?:\s+|)(?:reknown|reknowned|renowned|renown)\b)/gmi,

css: { "background-color": "#ea985d" },

text_matcher: true,

},

// Language 3

{

comment: 'Promotional phrasing',

// more bad regex!

regex: /\b(?:own\s+new\s+world|eponymous|renowned|being\s+the\s+world|revolutionized|swiftly|(?:instant|growing)\s+popularity|clientele|breathes\s+life|coveted|(?:his|her|their)\s+audiences|ever\s+growing|upcoming\s+works)/gmi,

css: { "background-color": "#ea985d" },

text_matcher: true,

},

// Language 4

{

comment: 'Promotional phrasing',

// more bad regex!

regex: /\b(?:world\’s\s+leading|extensive\s+range|in\s+the\s+world|innovative|market\s+leading|cutting(?:\s+|-)edge|pushing\s+the\s+boundaries|comprehensive)/gmi,

css: { "background-color": "#ea985d" },

text_matcher: true,

},

// Language 5

{

comment: 'Promotional phrasing',

regex: /\b(?:entrepreneur|motivational\s+(?:speaker|writer|author)|influencer|social\s+media\s+personality|rising\s+star|up\s+and\s+coming|notable\s+for|featured\s+in|famous|celebrity)/gmi,

css: { "background-color": "#ea985d" },

text_matcher: true,

},

// Language 6

{

comment: 'Promotional phrasing',

regex: /\b(?:safe\s+shopping|fast\s+delivery|world\'?s\s+most|prime\s+goal)/gmi,

css: { "background-color": "#ea985d" },

text_matcher: true,

},

];

// Dynamically load a user's custom rules from User:USERNAME/extra-unreliable-rules.js

mw.loader.getScript('/w/index.php?title=User:' + encodeURIComponent(mw.config.get('wgUserName')) +

'/extra-unreliable-rules.js&action=raw&ctype=text/javascript')

.fail( function(e) {

// Something's gone very wrong

mw.log.error("Error retrieving your extra-unreliable-rules.js");

// More detailed error in the console if someone feels nice enough to file a bug report

console.log("Error getting local extra-unreliable-rules.js: " + e.message);

})

.done( function () {

// Script succeeded. You can use X now.

if (Array.isArray(window.ExtraUnreliableCustomRules)) {

unreliableCustomRules.forEach(function(customRule) {

if (!(customRule.regex instanceof RegExp) || (typeof customRule.css !== 'object')) {

return mw.log.warn("Error parsing custom unreliable links rule: ", rule);

}

rules.push(customRule);

});

}

})

.always( function () {

highlight();

});

var highlight = function() {

let n = mw.config.get('wgNamespaceNumber');

if (n === 0 || n == 118 || n === 2)

{

const text_rules = rules.filter(rule => rule.text_matcher);

// All text_rules are assumed to have the /mi flags when merged.

const merged_rule = new RegExp(`(?:${text_rules.reduce((accum, rule) => `${accum}|${rule.regex.source}`, "^\\b$")})`, 'mi');

// Due to limitations of this way of implementing it, only one rule's CSS and comment are used.

const first_rule = text_rules[0];

let final_css = "";

for (const i in first_rule.css) {

final_css += `${i}: ${first_rule.css[i]};`;

}

$('.mw-parser-output > p, .mw-parser-output > b, .mw-parser-output > i, .mw-parser-output > s, .mw-parser-output > code, .mw-parser-output > ul li, .mw-parser-output > ol:not(.references) li').each(function(_, para) {

const walker = document.createTreeWalker(para, NodeFilter.SHOW_TEXT);

while (walker.nextNode()) {

const text = walker.currentNode;

let m;

while (m = text.textContent.match(merged_rule)) {

const wrapper = document.createElement('strong');

wrapper.style.cssText = final_css;

wrapper.className = 'Moonythedwarf-extra-unreliable';

wrapper.title = first_rule.comment || '';

// Wrap the matched fragment of text in the tag

const range = new Range();

range.setStart(text, m.index);

range.setEnd(text, m.index + m[0].length);

range.surroundContents(wrapper);

// Skip past the wrapped text

walker.currentNode = wrapper.lastChild;

}

}

return true;

});

}

};

});