Untitled diff

Created Diff never expires
32 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
585 lines
38 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
590 lines
// ==UserScript==
// ==UserScript==
// @name Stack-Exchange-Editor-Toolkit
// @name Stack-Exchange-Editor-Toolkit
// @author Cameron Bernhardt (AstroCB)
// @author Cameron Bernhardt (AstroCB)
// @developer Jonathan Todd (jt0dd)
// @developer Jonathan Todd (jt0dd)
// @developer sathyabhat
// @developer sathyabhat
// @contributor Unihedron
// @contributor Unihedron
// @contributor Tiny Giant
// @contributor Tiny Giant
// @contributor Mogsdad
// @contributor Mogsdad
// @grant none
// @grant none
// @license MIT
// @license MIT
// @namespace http://github.com/AstroCB
// @namespace http://github.com/AstroCB
// @version 1.5.2.4
// @version 1.5.2.5
// @description Fix common grammar/usage annoyances on Stack Exchange posts with a click
// @description Fix common grammar/usage annoyances on Stack Exchange posts with a click
// @include *://*.stackexchange.com/questions/*
// @include *://*.stackexchange.com/questions/*
// @include *://stackoverflow.com/questions/*
// @include *://stackoverflow.com/questions/*
// @include *://stackoverflow.com/review/helper/*
// @include *://stackoverflow.com/review/helper/*
// @include *://meta.stackoverflow.com/questions/*
// @include *://meta.stackoverflow.com/questions/*
// @include *://serverfault.com/questions/*
// @include *://serverfault.com/questions/*
// @include *://meta.serverfault.com/questions/*
// @include *://meta.serverfault.com/questions/*
// @include *://superuser.com/questions/*
// @include *://superuser.com/questions/*
// @include *://meta.superuser.com/questions/*
// @include *://meta.superuser.com/questions/*
// @include *://askubuntu.com/questions/*
// @include *://askubuntu.com/questions/*
// @include *://meta.askubuntu.com/questions/*
// @include *://meta.askubuntu.com/questions/*
// @include *://stackapps.com/questions/*
// @include *://stackapps.com/questions/*
// @include *://*.stackexchange.com/posts/*
// @include *://*.stackexchange.com/posts/*
// @include *://stackoverflow.com/posts/*
// @include *://stackoverflow.com/posts/*
// @include *://meta.stackoverflow.com/posts/*
// @include *://meta.stackoverflow.com/posts/*
// @include *://serverfault.com/posts/*
// @include *://serverfault.com/posts/*
// @include *://meta.serverfault.com/posts/*
// @include *://meta.serverfault.com/posts/*
// @include *://superuser.com/posts/*
// @include *://superuser.com/posts/*
// @include *://meta.superuser.com/posts/*
// @include *://meta.superuser.com/posts/*
// @include *://askubuntu.com/posts/*
// @include *://askubuntu.com/posts/*
// @include *://meta.askubuntu.com/posts/*
// @include *://meta.askubuntu.com/posts/*
// @include *://stackapps.com/posts/*
// @include *://stackapps.com/posts/*
// @include *://*.stackexchange.com/review/*
// @include *://*.stackexchange.com/review/*
// @include *://stackoverflow.com/review/*
// @include *://stackoverflow.com/review/*
// @include *://meta.stackoverflow.com/review/*
// @include *://meta.stackoverflow.com/review/*
// @include *://serverfault.com/review/*
// @include *://serverfault.com/review/*
// @include *://meta.serverfault.com/review/*
// @include *://meta.serverfault.com/review/*
// @include *://superuser.com/review/*
// @include *://superuser.com/review/*
// @include *://meta.superuser.com/review/*
// @include *://meta.superuser.com/review/*
// @include *://askubuntu.com/review/*
// @include *://askubuntu.com/review/*
// @include *://meta.askubuntu.com/review/*
// @include *://meta.askubuntu.com/review/*
// @include *://stackapps.com/review/*
// @include *://stackapps.com/review/*
// @exclude *://*.stackexchange.com/questions/tagged/*
// @exclude *://*.stackexchange.com/questions/tagged/*
// @exclude *://stackoverflow.com/questions/tagged/*
// @exclude *://stackoverflow.com/questions/tagged/*
// @exclude *://meta.stackoverflow.com/questions/tagged/*
// @exclude *://meta.stackoverflow.com/questions/tagged/*
// @exclude *://serverfault.com/questions/tagged/*
// @exclude *://serverfault.com/questions/tagged/*
// @exclude *://meta.serverfault.com/questions/*
// @exclude *://meta.serverfault.com/questions/*
// @exclude *://superuser.com/questions/tagged/*
// @exclude *://superuser.com/questions/tagged/*
// @exclude *://meta.superuser.com/questions/tagged/*
// @exclude *://meta.superuser.com/questions/tagged/*
// @exclude *://askubuntu.com/questions/tagged/*
// @exclude *://askubuntu.com/questions/tagged/*
// @exclude *://meta.askubuntu.com/questions/tagged/*
// @exclude *://meta.askubuntu.com/questions/tagged/*
// @exclude *://stackapps.com/questions/tagged/*
// @exclude *://stackapps.com/questions/tagged/*
// ==/UserScript==
// ==/UserScript==
var main = function() {
var main = function() {
// Define app namespace
// Define app namespace
function EditorToolkit(targetID) {
function EditorToolkit(inline, targetID) {
if (!(this instanceof EditorToolkit)) return false;
if (!(this instanceof EditorToolkit)) return false;


var App = this;
var App = this;


// Place edit items here
// Place edit items here
App.items = [];
App.items = [];


// Place selected jQuery items here
// Place selected jQuery items here
App.selections = {};
App.selections = {};


// Place "global" app data here
// Place "global" app data here
App.globals = {};
App.globals = {};


// Place "helper" functions here
// Place "helper" functions here
App.funcs = {};
App.funcs = {};


//Preload icon alt
//Preload icon alt
var SEETicon = new Image();
var SEETicon = new Image();


SEETicon.src = '//i.imgur.com/d5ZL09o.png';
SEETicon.src = '//i.imgur.com/d5ZL09o.png';


// Define variables for later use
// Define variables for later use
App.globals.barReady = false;
App.globals.barReady = false;
App.globals.editsMade = false;
App.globals.editsMade = false;
App.globals.editCount = 0;
App.globals.editCount = 0;
App.globals.infoContent = '';
App.globals.infoContent = '';


// Check if there was an ID passed (if not, use question ID from URL);
// Check if there was an ID passed (if not, use question ID from URL);
if (!targetID) targetID = window.location.href.match(/\/(\d+)\//g)[0].split("/").join("");
if (!targetID) targetID = window.location.href.match(/\/(\d+)\//g)[0].split("/").join("");
App.globals.targetID = targetID;
App.globals.targetID = targetID;
App.globals.inline = inline;


App.globals.spacerHTML = '<li class="wmd-spacer wmd-spacer3" id="wmd-spacer3-' + App.globals.targetID + '" style="left: 400px !important;"></li>';
App.globals.spacerHTML = '<li class="wmd-spacer wmd-spacer3" id="wmd-spacer3-' + App.globals.targetID + '" style="left: 400px !important;"></li>';


App.selections.buttonWrapper = $('<div class="ToolkitButtonWrapper"/>');
App.selections.buttonWrapper = $('<div class="ToolkitButtonWrapper"/>');
App.selections.buttonFix = $('<button class="wmd-button ToolkitFix" />');
App.selections.buttonFix = $('<button class="wmd-button ToolkitFix" />');
App.selections.buttonInfo = $('<div class="ToolkitInfo">');
App.selections.buttonInfo = $('<div class="ToolkitInfo">');


App.selections.buttonWrapper.append(App.selections.buttonFix);
App.selections.buttonWrapper.append(App.selections.buttonFix);
App.selections.buttonWrapper.append(App.selections.buttonInfo);
App.selections.buttonWrapper.append(App.selections.buttonInfo);


App.globals.reasons = [];
App.globals.reasons = [];
App.globals.numReasons = 0;
App.globals.numReasons = 0;


App.globals.replacedStrings = {
App.globals.replacedStrings = {
"block": [],
"block": [],
"inline": []
"inline": []
};
};
App.globals.placeHolders = {
App.globals.placeHolders = {
"block": "_xCodexBlockxPlacexHolderx_",
"block": "_xCodexBlockxPlacexHolderx_",
"inline": "_xCodexInlinexPlacexHolderx_"
"inline": "_xCodexInlinexPlacexHolderx_"
};
};
App.globals.checks = {
App.globals.checks = {
"block": /( )+.*/gm,
"block": /( )+.*/gm,
"inline": /`.*`/gm
"inline": /`.*`/gm
};
};


// Assign modules here
// Assign modules here
App.globals.pipeMods = {};
App.globals.pipeMods = {};


// Define order in which mods affect here
// Define order in which mods affect here
App.globals.order = ["omit", "edit", "replace"];
App.globals.order = ["omit", "edit", "replace"];




// Define edit rules
// Define edit rules
App.edits = {
App.edits = {
i: {
i: {
expr: /(^|\s|\()i(\s|,|\.|!|\?|;|\/|\)|'|$)/gm,
expr: /(^|\s|\()i(\s|,|\.|!|\?|;|\/|\)|'|$)/gm,
replacement: "$1I$2",
replacement: "$1I$2",
reason: "in English, the personal pronoun is 'I'"
reason: "in English, the personal pronoun is 'I'"
},
},
so: {
so: {
expr: /(^|\s)[Ss]tack\s*overflow|StackOverflow(.|$)/gm,
expr: /(^|\s)[Ss]tack\s*overflow|StackOverflow(.|$)/gm,
replacement: "$1Stack Overflow$2",
replacement: "$1Stack Overflow$2",
reason: "'Stack Overflow' is the legal name"
reason: "'Stack Overflow' is the legal name"
},
},
se: {
se: {
expr: /(^|\s)[Ss]tack\s*exchange|StackExchange(.|$)/gm,
expr: /(^|\s)[Ss]tack\s*exchange|StackExchange(.|$)/gm,
replacement: "$1Stack Exchange$2",
replacement: "$1Stack Exchange$2",
reason: "'Stack Exchange' is the legal name"
reason: "'Stack Exchange' is the legal name"
},
},
expansionSO: {
expansionSO: {
expr: /(^|\s)SO(\s|,|\.|!|\?|;|\/|\)|$)/gm,
expr: /(^|\s)SO(\s|,|\.|!|\?|;|\/|\)|$)/gm,
replacement: "$1Stack Overflow$2",
replacement: "$1Stack Overflow$2",
reason: "'SO' expansion"
reason: "'SO' expansion"
},
},
expansionSE: {
expansionSE: {
expr: /(^|\s)SE(\s|,|\.|!|\?|;|\/|\)|$)/gm,
expr: /(^|\s)SE(\s|,|\.|!|\?|;|\/|\)|$)/gm,
replacement: "$1Stack Exchange$2",
replacement: "$1Stack Exchange$2",
reason: "'SE' expansion"
reason: "'SE' expansion"
},
},
javascript: {
javascript: {
expr: /(^|\s)[Jj]ava\s*[Ss]cript(.|$)/gm,
expr: /(^|\s)[Jj]ava\s*[Ss]cript(.|$)/gm,
replacement: "$1JavaScript$2",
replacement: "$1JavaScript$2",
reason: "'JavaScript' is the proper capitalization"
reason: "'JavaScript' is the proper capitalization"
},
},
jsfiddle: {
jsfiddle: {
expr: /(^|\s)[Jj][Ss]\s*[Ff]iddle(.|$)/gm,
expr: /(^|\s)[Jj][Ss]\s*[Ff]iddle(.|$)/gm,
replacement: "$1JSFiddle$2",
replacement: "$1JSFiddle$2",
reason: "'JSFiddle' is the currently accepted capitalization"
reason: "'JSFiddle' is the currently accepted capitalization"
},
},
caps: {
caps: {
expr: /^(?!https?)([a-z])/gm,
expr: /^(?!https?)([a-z])/gm,
replacement: "$1",
replacement: "$1",
reason: "copy edited"
reason: "copy edited"
},
},
jquery: {
jquery: {
expr: /(^|\s)[Jj][Qq]uery(.|$)/gm,
expr: /(^|\s)[Jj][Qq]uery(.|$)/gm,
replacement: "$1jQuery$2",
replacement: "$1jQuery$2",
reason: "'jQuery' is the proper capitalization"
reason: "'jQuery' is the proper capitalization"
},
},
html: {
html: {
expr: /(^|\s)[Hh]tml([5]?)\b(\S|)(?!\S)/gm,
expr: /(^|\s)[Hh]tml([5]?)\b(\S|)(?!\S)/gm,
replacement: "$1HTML$2$3",
replacement: "$1HTML$2$3",
reason: "HTML stands for HyperText Markup Language"
reason: "HTML stands for HyperText Markup Language"
},
},
css: {
css: {
expr: /(^|\s)[Cc]ss\b(\S|)(?!\S)/gm,
expr: /(^|\s)[Cc]ss\b(\S|)(?!\S)/gm,
replacement: "$1CSS$2",
replacement: "$1CSS$2",
reason: "CSS stands for Cascading Style Sheets"
reason: "CSS stands for Cascading Style Sheets"
},
},
json: {
json: {
expr: /(^|\s)[Jj]son\b(\S|)(?!\S)/gm,
expr: /(^|\s)[Jj]son\b(\S|)(?!\S)/gm,
replacement: "$1JSON$2",
replacement: "$1JSON$2",
reason: "JSON stands for JavaScript Object Notation"
reason: "JSON stands for JavaScript Object Notation"
},
},
ajax: {
ajax: {
expr: /(^|\s)ajax\b(\S|)(?!\S)/gm,
expr: /(^|\s)ajax\b(\S|)(?!\S)/gm,
replacement: "$1AJAX$2",
replacement: "$1AJAX$2",
reason: "AJAX stands for Asynchronous JavaScript and XML"
reason: "AJAX stands for Asynchronous JavaScript and XML"
},
},
angular: {
angular: {
expr: /[Aa]ngular[Jj][Ss]/g,
expr: /[Aa]ngular[Jj][Ss]/g,
replacement: "AngularJS",
replacement: "AngularJS",
reason: "'AngularJS is the proper capitalization"
reason: "'AngularJS is the proper capitalization"
},
},
thanks: {
thanks: {
expr: /(thanks|pl(?:ease|z|s)\s+h[ea]lp|cheers|regards|thx|thank\s+you|my\s+first\s+question|kindly\shelp).*$/gmi,
expr: /(thanks|pl(?:ease|z|s)\s+h[ea]lp|cheers|regards|thx|thank\s+you|my\s+first\s+question|kindly\shelp).*$/gmi,
replacement: "",
replacement: "",
reason: "'$1' is unnecessary noise"
reason: "'$1' is unnecessary noise"
},
},
commas: {
commas: {
expr: /,([^\s])/g,
expr: /,([^\s])/g,
replacement: ", $1",
replacement: ", $1",
reason: "punctuation & spacing"
reason: "punctuation & spacing"
},
},
php: {
php: {
expr: /(^|\s)[Pp]hp\b(\S|)(?!\S)/gm,
expr: /(^|\s)[Pp]hp\b(\S|)(?!\S)/gm,
replacement: "$1PHP$2",
replacement: "$1PHP$2",
reason: "PHP stands for PHP: Hypertext Preprocessor"
reason: "PHP stands for PHP: Hypertext Preprocessor"
},
},
hello: {
hello: {
expr: /(?:^|\s)(hi\s+guys|hi|hello|good\s(?:evening|morning|day|afternoon))(?:\.|!|\ )/gmi,
expr: /(?:^|\s)(hi\s+guys|hi|hello|good\s(?:evening|morning|day|afternoon))(?:\.|!|\ )/gmi,
replacement: "",
replacement: "",
reason: "greetings like '$1' are unnecessary noise"
reason: "greetings like '$1' are unnecessary noise"
},
},
edit: {
edit: {
expr: /(?:^\**)(edit|update):?(?:\**):?/gmi,
expr: /(?:^\**)(edit|update):?(?:\**):?/gmi,
replacement: "",
replacement: "",
reason: "Stack Exchange has an advanced revision history system: 'Edit' or 'Update' is unnecessary"
reason: "Stack Exchange has an advanced revision history system: 'Edit' or 'Update' is unnecessary"
},
},
voting: {
voting: {
expr: /([Dd]own|[Uu]p)[\s*\-]vot/g,
expr: /([Dd]own|[Uu]p)[\s*\-]vot/g,
replacement: "$1vote",
replacement: "$1vote",
reason: "the proper spelling (despite the tag name) is '$1vote' (one word)"
reason: "the proper spelling (despite the tag name) is '$1vote' (one word)"
},
},
mysite: {
mysite: {
expr: /mysite\./g,
expr: /mysite\./g,
replacement: "example.",
replacement: "example.",
reason: "links to mysite.domain are not allowed: use example.domain instead"
reason: "links to mysite.domain are not allowed: use example.domain instead"
},
},
c: {
c: {
expr: /(^|\s)c(#|\++|\s|$)/gm,
expr: /(^|\s)c(#|\++|\s|$)/gm,
replacement: "$1C$2",
replacement: "$1C$2",
reason: "C$2 is the proper capitalization"
reason: "C$2 is the proper capitalization"
},
},
java: {
java: {
expr: /(^|\s)java\b(\S|)(?!\S)/gmi,
expr: /(^|\s)java\b(\S|)(?!\S)/gmi,
replacement: "$1Java$2",
replacement: "$1Java$2",
reason: "Java should be capitalized"
reason: "Java should be capitalized"
},
},
sql: {
sql: {
expr: /(^|\s)[Ss]ql\b(\S|)(?!\S)/gm,
expr: /(^|\s)[Ss]ql\b(\S|)(?!\S)/gm,
replacement: "$1SQL$2",
replacement: "$1SQL$2",
reason: "SQL is the proper capitalization"
reason: "SQL is the proper capitalization"
},
},
sqlite: {
sqlite: {
expr: /(^|\s)[Ss]qlite([0-9]*)\b(\S|)(?!\S)/gm,
expr: /(^|\s)[Ss]qlite([0-9]*)\b(\S|)(?!\S)/gm,
replacement: "$1SQLite$2$3",
replacement: "$1SQLite$2$3",
reason: "SQLite is the proper capitalization"
reason: "SQLite is the proper capitalization"
},
},
android: {
android: {
expr: /(^|\s)android\b(\S|)(?!\S)/gmi,
expr: /(^|\s)android\b(\S|)(?!\S)/gmi,
replacement: "$1Android$2",
replacement: "$1Android$2",
reason: "Android should be capitalized"
reason: "Android should be capitalized"
},
},
oracle: {
oracle: {
expr: /(^|\s)oracle\b(\S|)(?!\S)/gmi,
expr: /(^|\s)oracle\b(\S|)(?!\S)/gmi,
replacement: "$1Oracle$2",
replacement: "$1Oracle$2",
reason: "Oracle should be capitalized"
reason: "Oracle should be capitalized"
},
},
windows: {
windows: {
expr: /(win|windows(?:\ ?)(\s[0-9]+))\b(\S|)(?!\S)/igm,
expr: /(win|windows(?:\ ?)(\s[0-9]+))\b(\S|)(?!\S)/igm,
replacement: "Windows$2$3",
replacement: "Windows$2$3",
reason: "Windows should be capitalized"
reason: "Windows should be capitalized"
},
},
windowsXP: {
windowsXP: {
expr: /(win|windows(?:\ ?)(\sxp))\b(\S|)(?!\S)/igm,
expr: /(win|windows(?:\ ?)(\sxp))\b(\S|)(?!\S)/igm,
replacement: "Windows XP$3",
replacement: "Windows XP$3",
reason: "Windows XP should be capitalized"
reason: "Windows XP should be capitalized"
},
},
windowsVista: {
windowsVista: {
expr: /(win|windows(?:\ ?)(\svista))\b(\S|)(?!\S)/igm,
expr: /(win|windows(?:\ ?)(\svista))\b(\S|)(?!\S)/igm,
replacement: "Windows Vista$3",
replacement: "Windows Vista$3",
reason: "Windows Vista should be capitalized"
reason: "Windows Vista should be capitalized"
},
},
ubuntu: {
ubuntu: {
expr: /(ubunto|ubunut|ubunutu|ubunu|ubntu|ubutnu|ubanto[o]+|unbuntu|ubunt|ubutu)\b(\S|)(?!\S)/igm,
expr: /(ubunto|ubunut|ubunutu|ubunu|ubntu|ubutnu|ubanto[o]+|unbuntu|ubunt|ubutu)\b(\S|)(?!\S)/igm,
replacement: "Ubuntu$2",
replacement: "Ubuntu$2",
reason: "corrected Ubuntu spelling"
reason: "corrected Ubuntu spelling"
},
},
linux: {
linux: {
expr: /(linux)\b(\S|)(?!\S)/igm,
expr: /(linux)\b(\S|)(?!\S)/igm,
replacement: "Linux$2",
replacement: "Linux$2",
reason: "Linux should be capitalized"
reason: "Linux should be capitalized"
},
},
apostrophes: {
apostrophes: {
expr: /(^|\s)(can|doesn|don|won|hasn|isn|didn)t(\s|$)/gmi,
expr: /(^|\s)(can|doesn|don|won|hasn|isn|didn)t(\s|$)/gmi,
replacement: "$1$2't$3",
replacement: "$1$2't$3",
reason: "English contractions use apostrophes"
reason: "English contractions use apostrophes"
},
},
ios: {
ios: {
expr: /\b(?:ios|iOs|ioS|IOS|Ios|IoS|ioS)\b(\S|)(?!\S)/gm,
expr: /\b(?:ios|iOs|ioS|IOS|Ios|IoS|ioS)\b(\S|)(?!\S)/gm,
replacement: "iOS$1",
replacement: "iOS$1",
reason: "the proper usage is 'iOS'"
reason: "the proper usage is 'iOS'"
},
},
iosnum: {
iosnum: {
expr: /\b(?:ios|iOs|ioS|IOS|Ios|IoS|ioS)([0-9]?)\b(\S|)(?!\S)/gm,
expr: /\b(?:ios|iOs|ioS|IOS|Ios|IoS|ioS)([0-9]?)\b(\S|)(?!\S)/gm,
replacement: "iOS $1$2",
replacement: "iOS $1$2",
reason: "the proper usage is 'iOS' followed by a space and the version number"
reason: "the proper usage is 'iOS' followed by a space and the version number"
},
},
yell: {
yell: {
expr: /^((?=.*[A-Z])[^a-z]*)$/g,
expr: /^((?=.*[A-Z])[^a-z]*)$/g,
replacement: "$1",
replacement: "$1",
reason: "no need to yell"
reason: "no need to yell"
},
},
wordpress: {
wordpress: {
expr: /[Ww]ordpress/g,
expr: /[Ww]ordpress/g,
replacement: "WordPress",
replacement: "WordPress",
reason: "'WordPress' is the proper capitalization"
reason: "'WordPress' is the proper capitalization"
},
},
google: {
google: {
expr: /(google)\b(\S|)(?!\S)/igm,
expr: /(google)\b(\S|)(?!\S)/igm,
replacement: "Google$2",
replacement: "Google$2",
reason: "Google is the proper capitalization"
reason: "Google is the proper capitalization"
},
},
mysql: {
mysql: {
expr: /(mysql)\b(\S|)(?!\S)/igm,
expr: /(mysql)\b(\S|)(?!\S)/igm,
replacement: "MySQL$2",
replacement: "MySQL$2",
reason: "MySQL is the proper capitalization"
reason: "MySQL is the proper capitalization"
},
},
apache: {
apache: {
expr: /(apache)\b(\S|)(?!\S)/igm,
expr: /(apache)\b(\S|)(?!\S)/igm,
replacement: "Apache$2",
replacement: "Apache$2",
reason: "Apache is the proper capitalization"
reason: "Apache is the proper capitalization"
},
},
git: {
git: {
expr: /(^|\s)(git|GIT)\b(\S|)(?!\S)/gm,
expr: /(^|\s)(git|GIT)\b(\S|)(?!\S)/gm,
replacement: "$1Git$3",
replacement: "$1Git$3",
reason: "Git is the proper capitalization"
reason: "Git is the proper capitalization"
},
},
harddisk: {
harddisk: {
expr: /(hdd|harddisk)\b(\S|)(?!\S)/igm,
expr: /(hdd|harddisk)\b(\S|)(?!\S)/igm,
replacement: "hard disk$2",
replacement: "hard disk$2",
reason: "Hard disk is the proper capitalization"
reason: "Hard disk is the proper capitalization"
},
},
github: {
github: {
expr: /\b([gG]ithub|GITHUB)\b(\S|)(?!\S)/gm,
expr: /\b([gG]ithub|GITHUB)\b(\S|)(?!\S)/gm,
replacement: "GitHub$2",
replacement: "GitHub$2",
reason: "GitHub is the proper capitalization"
reason: "GitHub is the proper capitalization"
},
},
facebook: {
facebook: {
expr: /\b([fF]acebook|FACEBOOK)\b(\S|)(?!\S)/gm,
expr: /\b([fF]acebook|FACEBOOK)\b(\S|)(?!\S)/gm,
replacement: "Facebook$2",
replacement: "Facebook$2",
reason: "Facebook is the proper capitalization"
reason: "Facebook is the proper capitalization"
},
},
python: {
python: {
expr: /(^|\s)[Pp]ython(.|$)/gm,
expr: /(^|\s)[Pp]ython(.|$)/gm,
replacement: "$1Python$2",
replacement: "$1Python$2",
reason: "'Python' is the proper capitalization"
reason: "'Python' is the proper capitalization"
},
},
im: {
im: {
expr: /(^|\s|\()im(\s|,|\.|!|\?|;|\/|\)|'|$)/gm,
expr: /(^|\s|\()im(\s|,|\.|!|\?|;|\/|\)|'|$)/gm,
replacement: "$1I'm$2",
replacement: "$1I'm$2",
reason: "in English, the personal pronoun is 'I'"
reason: "in English, the personal pronoun is 'I'"
},
},
ive: {
ive: {
expr: /(^|\s|\()ive(\s|,|\.|!|\?|;|\/|\)|'|$)/gm,
expr: /(^|\s|\()ive(\s|,|\.|!|\?|;|\/|\)|'|$)/gm,
replacement: "$1I've$2",
replacement: "$1I've$2",
reason: "in English, the personal pronoun is 'I'"
reason: "in English, the personal pronoun is 'I'"
},
},
ur: {
ur: {
expr: /(^|\s|\()ur(\s|,|\.|!|\?|;|\/|\)|'|$)/gm,
expr: /(^|\s|\()ur(\s|,|\.|!|\?|;|\/|\)|'|$)/gm,
replacement: "$1you are$2",
replacement: "$1you are$2",
reason: "de-text"
reason: "de-text"
},
},
u: {
u: {
expr: /(^|\s|\()u(\s|,|\.|!|\?|;|\/|\)|'|$)/gm,
expr: /(^|\s|\()u(\s|,|\.|!|\?|;|\/|\)|'|$)/gm,
replacement: "$1you$2",
replacement: "$1you$2",
reason: "de-text"
reason: "de-text"
},
},
allways: {
allways: {
expr: /(^|\s|\()(a)llways(\s|,|\.|!|\?|;|\/|\)|'|$)/gmi,
expr: /(^|\s|\()(a)llways(\s|,|\.|!|\?|;|\/|\)|'|$)/gmi,
replacement: "$1$2lways$3",
replacement: "$1$2lways$3",
reason: "spelling"
reason: "spelling"
},
},
appreciated: {
appreciated: {
expr: /(?:[\s-,']\w*)*(help|suggestion|advice).*(?:appreciated).*/gmi,
expr: /(?:[\s-,']\w*)*(help|suggestion|advice).*(?:appreciated).*/gmi,
replacement: "",
replacement: "",
reason: "$1 requests are unnecessary noise"
reason: "$1 requests are unnecessary noise"
},
},
hopeMaybeHelps: {
hopeMaybeHelps: {
expr: /(?:[\s-,']\w*)*(maybe|hope)+(?:[\s-,']\w*)*\s(help[s]*)(?:[\s-,']\w*)*[\.!?]/gmi,
expr: /(?:[\s-,']\w*)*(maybe|hope)+(?:[\s-,']\w*)*\s(help[s]*)(?:[\s-,']\w*)*[\.!?]/gmi,
replacement: "",
replacement: "",
reason: "$1...$2 is unnecessary noise"
reason: "$1...$2 is unnecessary noise"
},
},
regex: {
regex: {
expr: /regex(p)?/gmi,
expr: /regex(p)?/gmi,
replacement: function(match,p){ return "RegEx"+((p === undefined)?"":p).toLowerCase(); },
replacement: function(match,p){ return "RegEx"+((p === undefined)?"":p).toLowerCase(); },
reason: "RegEx or RegExp are the correct capitalizations"
reason: "RegEx or RegExp are the correct capitalizations"
},
},
multiplesymbols: {
multiplesymbols: {
expr: /\?\?+/gm,
expr: /\?\?+/gm,
replacement: "?",
replacement: "?",
reason: "One question mark for one question"
reason: "One question mark for one question"
},
},
// Whitespace compression comes last
// Whitespace compression comes last
multiplespaces: {
multiplespaces: {
expr: /(\S) +(\S)/gm,
expr: /(\S) +(\S)/gm,
replacement: "$1 $2",
replacement: "$1 $2",
reason: "One space at a time"
reason: "One space at a time"
},
},
spacesbeforepunctuation: {
spacesbeforepunctuation: {
expr: / +([.,:;?!])/g,
//expr: / +([.,:;?!])/g,
expr: / +([.,:;?!])[^\w]/g,
replacement: "$1 ",
replacement: "$1 ",
reason: "punctuation & spacing"
reason: "punctuation & spacing"
},
},
spacesafterpunctuation: {
spacesafterpunctuation: {
expr: /([.,:;?!]) +/g,
expr: /([.,:;?!]) +/g,
replacement: "$1 ",
replacement: "$1 ",
reason: "punctuation & spacing"
reason: "punctuation & spacing"
},
},
leadingspace: {
leadingspace: {
expr: /^ +(\S)/gm,
expr: /^ +(\S)/gm,
replacement: "$1",
replacement: "$1",
reason: "punctuation & spacing"
reason: "punctuation & spacing"
},
},
blanklines: {
blanklines: {
expr: /(?:\s*[\r\n]){3,}/gm,
expr: /(?:\s*[\r\n]){3,}/gm,
replacement: "\n\n",
replacement: "\n\n",
reason: "punctuation & spacing"
reason: "punctuation & spacing"
},
},
endblanklines: {
endblanklines: {
expr: /[\s\r\n]+$/g,
expr: /[\s\r\n]+$/g,
replacement: "",
replacement: "",
reason: "punctuation & spacing"
reason: "punctuation & spacing"
}
}
};
};


// Populate funcs
// Populate funcs
App.popFuncs = function() {
App.popFuncs = function() {
// This is where the magic happens: this function takes a few pieces of information and applies edits to the post with a couple exceptions
// This is where the magic happens: this function takes a few pieces of information and applies edits to the post with a couple exceptions
App.funcs.fixIt = function(input, expression, replacement, reasoning) {
App.funcs.fixIt = function(input, expression, replacement, reasoning) {
// If there is nothing to search, exit
// If there is nothing to search, exit
if (!input) return false;
if (!input) return false;
// Scan the post text using the expression to see if there are any matches
// Scan the post text using the expression to see if there are any matches
var match = input.search(expression);
var match = input.search(expression);
// If so, increase the number of edits performed (used later for edit summary formation)
// If so, increase the number of edits performed (used later for edit summary formation)
if (match !== -1) {
if (match !== -1) {


// Later, this will store what is removed for the first case
// Later, this will store what is removed for the first case
var phrase;
var phrase;


// Then, perform the edits using replace()
// Then, perform the edits using replace()
// What follows is a series of exceptions, which I will explain below; I perform special actions by overriding replace()
// What follows is a series of exceptions, which I will explain below; I perform special actions by overriding replace()
// This is used for removing things entirely without giving a replacement; it matches the expression and then replaces it with nothing
// This is used for removing things entirely without giving a replacement; it matches the expression and then replaces it with nothing
if (replacement === "") {
if (replacement === "") {
var phrase2; // Hack on a hack - allow 2 replacements
var phrase2; // Hack on a hack - allow 2 replacements
input = input.replace(expression, function(data, match1, match2) {
input = input.replace(expression, function(data, match1, match2) {
// Save what is removed for the edit summary (see below)
// Save what is removed for the edit summary (see below)
phrase = match1;
phrase = match1;
phrase2 = match2;
phrase2 = match2;




// Replace with nothing
// Replace with nothing
return "";
return "";
});
});


// This is an interesting tidbit: if you want to make the edit summaries dynamic, you can keep track of a match that you receive
// This is an interesting tidbit: if you want to make the edit summaries dynamic, you can keep track of a match that you receive
// from overriding the replace() function and then use that in the summary
// from overriding the replace() function and then use that in the summary
reasoning = reasoning.replace("$1", phrase)
reasoning = reasoning.replace("$1", phrase)
.replace("$2", phrase2);
.replace("$2", phrase2);




// This allows me to combine the upvote and downvote replacement schemes into one
// This allows me to combine the upvote and downvote replacement schemes into one
} else if (replacement == "$1vote") {
} else if (replacement == "$1vote") {
input = input.replace(expression, function(data, match1) {
input = input.replace(expression, function(data, match1) {
phrase = match1;
phrase = match1;
return phrase + "vot";
return phrase + "vot";
});
});
reasoning = reasoning.replace("$1", phrase.toLowerCase());
reasoning = reasoning.replace("$1", phrase.toLowerCase());


// Fix all caps
// Fix all caps
} else if (reasoning === "no need to yell") {
} else if (reasoning === "no need to yell") {
input = input.replace(expression, function(data, match1) {
input = input.replace(expression, function(data, match1) {
return match1.substring(0, 1).toUpperCase() + match1.substring(1).toLowerCase();
return match1.substring(0, 1).toUpperCase() + match1.substring(1).toLowerCase();
});
});
// This is used to capitalize letters; it merely takes what is matched, uppercases it, and replaces what was matched with the uppercased version
// This is used to capitalize letters; it merely takes what is matched, uppercases it, and replaces what was matched with the uppercased version
} else if (replacement === "$1") {
} else if (replacement === "$1") {
input = input.replace(expression, function(data, match1) {
input = input.replace(expression, function(data, match1) {
return match1.toUpperCase();
return match1.toUpperCase();
});
});


// I can use C, C#, and C++ capitalization in one rule
// I can use C, C#, and C++ capitalization in one rule
} else if (replacement === "$1C$2") {
} else if (replacement === "$1C$2") {
var newPhrase;
var newPhrase;
input = input.replace(expression, function(data, match1, match2) {
input = input.replace(expression, function(data, match1, match2) {
newPhrase = match2;
newPhrase = match2;
return match1 + "C" + match2;
return match1 + "C" + match2;
});
});
reasoning = reasoning.replace("$2", newPhrase);
reasoning = reasoning.replace("$2", newPhrase);


// iOS numbering/spacing fixes
// iOS numbering/spacing fixes
} else if (replacement === "iOS $2") {
} else if (replacement === "iOS $2") {
input = input.replace(expression, function(data, match1) {
input = input.replace(expression, function(data, match1) {
if (match1.match(/\d/)) { // Is a number
if (match1.match(/\d/)) { // Is a number
return "iOS " + match1;
return "iOS " + match1;
}
}


return "iOS" + match1;
return "iOS" + match1;
});
});


// Default: just replace it with the indicated replacement
// Default: just replace it with the indicated replacement
} else {
} else {
input = input.replace(expression, replacement);
input = input.replace(expression, replacement);
}
}


// Return a dictionary with the reasoning for the fix and what is edited (used later to prevent duplicates in the edit summary)
// Return a dictionary with the reasoning for the fix and what is edited (used later to prevent duplicates in the edit summary)
return {
return {
reason: reasoning,
reason: reasoning,
fixed: input
fixed: input
};
};
} else {
} else {
// If nothing needs to be fixed, return null
// If nothing needs to be fixed, return null
return null;
return null;
}
}
};
};


// Omit code
// Omit code
App.funcs.omitCode = function(str, type) {
App.funcs.omitCode = function(str, type) {
str = str.replace(App.globals.checks[type], function(match) {
str = str.replace(App.globals.checks[type], function(match) {
App.globals.replacedStrings[type].push(match);
App.globals.replacedStrings[type].push(match);
return App.globals.placeHolders[type];
return App.globals.placeHolders[type];
});
});
return str;
return str;
};
};


// Replace code
// Replace code
App.funcs.replaceCode = function(str, type) {
App.funcs.replaceCode = function(str, type) {
for (var i = 0; i < App.globals.replacedStrings[type].length; i++) {
for (var i = 0; i < App.globals.replacedStrings[type].length; i++) {
str = str.replace(App.globals.placeHolders[type],
str = str.replace(App.globals.placeHolders[type],
App.globals.replacedStrings[type][i]);
App.globals.replacedStrings[type][i]);
}
}
return str;
return str;
};
};


// Eliminate duplicates in array (awesome method I found on SO, check it out!)
// From AstroCB: the original structure of the edit formation prevents duplicates.
// Unless you changed that structure somehow, this shouldn't be needed.
App.funcs.eliminateDuplicates = function(arr) {
var i, len = arr.length,
out = [],
obj = {};

for (i = 0; i < len; i++) {
obj[arr[i]] = 0;
}
for (i in obj) {
if (obj.hasOwnProperty(i)) { // Prevents messiness of for..in statements
out.push(i);
}
}
return out;
};

App.funcs.applyListeners = function() { // Removes default Stack Exchange listeners; see https://github.com/AstroCB/Stack-Exchange-Editor-Toolkit/issues/43
App.funcs.applyListeners = function() { // Removes default Stack Exchange listeners; see https://github.com/AstroCB/Stack-Exchange-Editor-Toolkit/issues/43
function removeEventListeners(e) {
function removeEventListeners(e) {
if (e.which === 13) {
if (e.which === 13) {
if (e.metaKey || e.ctrlKey) {
if (e.metaKey || e.ctrlKey) {
// CTRL/CMD + Enter -> Activate the auto-editor
// CTRL/CMD + Enter -> Activate the auto-editor
App.selections.buttonFix.click();
App.selections.buttonFix.click();
this.focus();
this.focus();
} else {
} else {
// It's impossible to remove the event listeners, so we have to clone the element without any listeners
// It's impossible to remove the event listeners, so we have to clone the element without any listeners
var elClone = this.cloneNode(true);
var elClone = this.cloneNode(true);
this.parentNode.replaceChild(elClone, this);
this.parentNode.replaceChild(elClone,
this);
App.selections.submitButton.click();
App.selections.submitButton.click();
}
}
}
}
}
}


// Tags box
// Tags box
App.selections.tagField.keydown(removeEventListeners);
App.selections.tagField.keydown(removeEventListeners);


// Edit summary box
// Edit summary box
App.selections.summaryBox.keydown(removeEventListeners);
App.selections.summaryBox.keydown(removeEventListeners);
};
};


// Wait for relevant dynamic content to finish loading
// Wait for relevant dynamic content to finish loading
App.funcs.dynamicDelay = function(callback) {
App.funcs.dynamicDelay = function(callback) {
setTimeout(function() {
if (App.globals.inline) { // Inline editing
App.selections.buttonBar = $('#wmd-button-bar-' + App.globals.targetID);
App.selections.buttonBar.unbind();
setTimeout(function() {
setTimeout(function() {
callback();
App.selections.buttonBar = $('#wmd-button-bar-' + App.globals.targetID);
}, 0);
App.selections.buttonBar.unbind();
}, 500);
setTimeout(function() {
};
callback();

}, 0);
// Populate or refresh DOM selections
}, 500);
App.funcs.popSelections = function() {
} else { // Question page editing
var targetID = App.globals.targetID;
App.selections.
var scope = $('div[data-questionid="' + targetID + '"]');
if (!scope.length) scope = $('div[data-answerid="' + targetID + '"]');
if (!scope.length) scope = '';
App.selections.redoButton = $('#wmd-redo-button-' + targetID, scope);
App.selections.bodyBox = $("#wmd-input-" + targetID, scope);
App.selections.titleBox = $('[class*="title-field"]', scope);
App.selections.summaryBox = $("#edit-comment-" + targetID, scope);
App.selections.tagField = $($(".tag-editor")[0], scope);
App.selections.submitButton = $("#submit-button-" + targetID, scope);
};

// Populate edit item sets from DOM selections
App.funcs.popItems = function() {
App.items[0] = {
title: String(App.selections.titleBox.v