").append(m.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},m.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){m.fn[b]=function(a){return this.on(b,a)}}),m.expr.filters.animated=function(a){return m.grep(m.timers,function(b){return a===b.elem}).length};var cc=a.document.documentElement;function dc(a){return m.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}m.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=m.css(a,"position"),l=m(a),n={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=m.css(a,"top"),i=m.css(a,"left"),j=("absolute"===k||"fixed"===k)&&m.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),m.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(n.top=b.top-h.top+g),null!=b.left&&(n.left=b.left-h.left+e),"using"in b?b.using.call(a,n):l.css(n)}},m.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){m.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,m.contains(b,e)?(typeof e.getBoundingClientRect!==K&&(d=e.getBoundingClientRect()),c=dc(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===m.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),m.nodeName(a[0],"html")||(c=a.offset()),c.top+=m.css(a[0],"borderTopWidth",!0),c.left+=m.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-m.css(d,"marginTop",!0),left:b.left-c.left-m.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||cc;while(a&&!m.nodeName(a,"html")&&"static"===m.css(a,"position"))a=a.offsetParent;return a||cc})}}),m.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);m.fn[a]=function(d){return V(this,function(a,d,e){var f=dc(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?m(f).scrollLeft():e,c?e:m(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),m.each(["top","left"],function(a,b){m.cssHooks[b]=La(k.pixelPosition,function(a,c){return c?(c=Ja(a,b),Ha.test(c)?m(a).position()[b]+"px":c):void 0})}),m.each({Height:"height",Width:"width"},function(a,b){m.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){m.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return V(this,function(b,c,d){var e;return m.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?m.css(b,c,g):m.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),m.fn.size=function(){return this.length},m.fn.andSelf=m.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return m});var ec=a.jQuery,fc=a.$;return m.noConflict=function(b){return a.$===m&&(a.$=fc),b&&a.jQuery===m&&(a.jQuery=ec),m},typeof b===K&&(a.jQuery=a.$=m),m});
6 |
--------------------------------------------------------------------------------
/js/squanchify.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Nic Hite
2 | // Licensed under the MIT license, read LICENSE.txt
3 | $(document).ready(function(){
4 |
5 | /* Oh geez, oh man, Rick...I-I guess I'll start it off. Preferences are in
6 | Chrome storage, right?*/
7 | var origLength = document.links.length;
8 | toSquanchOrNotToSquanch();
9 |
10 | /* If people have endless scrolling on, Morty, I'm...I'm gonna make
11 | sure those assholes don't lose their squanch. You-you gotta keep
12 | the squanch GOING, Morty. More. MORE! Let's see where this goes! */
13 | $(document).on("scroll",debounce(function(){
14 |
15 | /* Huh? checking document links length? I don't get it, Rick! I'm losing
16 | it, man! */
17 | /* Morty, I'm gonna need you to quit your bitching and keep typing. We only
18 | want to re-squanchify if more content got loaded from endless scrolling.
19 | You'd know that if...if you were paying att--any attention, MORTY.*/
20 | if(document.links.length > origLength) {
21 | toSquanchOrNotToSquanch();
22 | origLength = document.links.length;
23 | }
24 | }, 0));
25 | });
26 |
27 | // squanchiness is value that is equal to the threshold a randomly generated
28 | // number from 0-1 (using Math.random()) must be greater than to squanch.
29 | // The lower the squanchiness, the higher propability a word will be squanched.
30 | // Kinda the opposite of what you'd expect. Maybe I should change that.
31 | var squanchify = function(squanchiness){
32 |
33 | // Skip all prepositions, all forms of pronouns, etc--this way all sentences
34 | // stay intact
35 | var unsquanchables = ["a","aboard","about","above","absent","across","after",
36 | "against","along","alongside","amid","amidst","among","an","and","are","around","as","at",
37 | "atop","before","behind","below","beneath","beside","between","by","despite",
38 | "down","during","except","following","for","from","he","her","hers","him","his","i","i'd","i'm","i've","in","is","inside","into",
39 | "like","mid","minus","near","next","notwithstanding","of","off","on","onto",
40 | "opposite","or","out","outside","over","past","plus","regarding","round","she",
41 | "since","than","that","the","their","them","they","they've","those","through","throughout","till",
42 | "times","to","toward","under","underneath","until","up","upon","we","which","who",
43 | "whom","whose","with","within","without","you"];
44 |
45 | // we want to squanch gerunds, but let's leave these ones out--we want all nouns
46 | // to turn to 'squanch'
47 | var ingExceptions = ["bling","bring","ceiling","ching","cling","ding","fling","king",
48 | "ping","ring","sing","sling","spring","sting","string","swing","thing","viking","wing","wring","zing"];
49 |
50 | // Words that end with 'ly' but aren't adverb--we'll need to handle these differently
51 | var lyExceptions = ["ally","anomaly", "apply", "assembly", "belly", "bely", "bodily", "bubbly", "bully",
52 | "burly", "chilly", "comely", "comply", "costly", "courtly", "cuddly", "curly", "daily", "dally",
53 | "dastardly", "deadly", "deathly", "disorderly", "doily", "dolly", "dragonfly", "early", "family",
54 | "fly", "friendly", "frilly", "ghastly", "goodly", "gravelly", "grisly", "gully", "heavenly", "hilly",
55 | "holly", "holy", "homely", "homily", "hourly", "imply", "jelly", "jolly", "kindly", "leisurely",
56 | "likely", "lily", "lively", "lonely", "lovely", "lowly", "mannerly", "mealy", "measly", "melancholy",
57 | "monopoly", "monthly", "multiply", "nightly", "oily", "only", "orderly", "pearly", "pebbly", "ply",
58 | "rally", "rarely", "rely", "reply", "scaly", "shapely", "sickly", "silly", "sly", "smelly", "sprightly",
59 | "squiggly", "stately", "steely", "supply", "supply", "surly", "tally", "timely", "ugly", "unlikely",
60 | "weekly", "wily", "wobbly", "wooly", "worldly", "wrinkly", "yearly"];
61 |
62 | // A full-scale DFS through the DOM
63 | var listOfSelectors = ["em","a","span","li","p","h1","h1","h2","h3","h4","h5","h6","div"];
64 |
65 | // Selectively going through the DOM of any arbitrary site is messy
66 | var tagRegex = /<.*>/g;
67 | var escapedHTMLRegex = /\&[a-z]+\;/i;
68 | var splitRegex = /\s+|\s*<.*>\s*/;
69 | var replacementRegex = /\w+\'*\w*/;
70 |
71 | listOfSelectors.forEach(function(selector){
72 |
73 | var DOMElements = document.querySelectorAll(selector);
74 | for (var i = 0; i < DOMElements.length; i++){
75 |
76 | var elementText = DOMElements[i].innerHTML.trim();
77 |
78 | if (elementText) {
79 |
80 | /* A-alright, we've gotta...we've gotta--UURP--pull out the LINKS here, Morty. The LINKS.
81 | If we don't do that, Morty, all the links are gonna break. They're gonna...break, Morty.
82 | It's just gonna be one...one big, big broken link party. Just sitting around
83 | being broken. Do you get it? */
84 | var possibleLinks = [];
85 | var currentLink;
86 | while ((currentLink = tagRegex.exec(elementText)) !== null)
87 | possibleLinks.push(currentLink);
88 |
89 | /* Oh man, Rick, it's...you know, like it's gonna be hard to, umm, put the links back
90 | in after we Squanchify everything, won't it? I mean...h-how are we gonna...even...know
91 | where to put them once we're done? */
92 | /* Relax, Morty. It's fine. Everything's fine. We'll just leave an empty string in the array
93 | where they came from and stick it back in later. No one will even know the difference,
94 | Morty. We're really...wuhh...flying under the radar with this one. */
95 | var unSquanchedWords = elementText.split(splitRegex);
96 |
97 | // don't squanch any elements that have already been squanched and no
98 | // empty strings
99 | if (!unSquanchedWords[0] || unSquanchedWords.join(" ").match(/squanch/i) ) {
100 | continue;
101 | }
102 |
103 | var length = unSquanchedWords.length;
104 | for (var j = 0; j < length; j++) {
105 |
106 | // Okay, Morty. Here's the word. Don't forget it.
107 | var wordToSquanch = unSquanchedWords[j];
108 |
109 | // Another (arbitrarily chosen) threshold is that we won't
110 | // squanch consecutive words unless the squanchiness is high
111 | var prevSquanch;
112 | if (j > 0 && squanchiness > 0.10)
113 | prevSquanch = unSquanchedWords[j-1].match(/squanch/i);
114 | var hasCharacters = wordToSquanch.match(/[a-z]/i);
115 |
116 | // Here's the main check to see if a word will be squanched
117 | if (Math.random() > squanchiness && hasCharacters && !prevSquanch) {
118 |
119 | // Commence squanching
120 | var squanchText;
121 | var isSquanchable = true;
122 |
123 | var ch = wordToSquanch.charAt(0);
124 | var isAllCaps = (wordToSquanch === wordToSquanch.toUpperCase());
125 | squanchText = (ch === ch.toUpperCase()) ? "Squanch" : "squanch";
126 |
127 | /* You can't just say "squanch" willy nilly with no--urgh--context, Morty.
128 | The real squanch comes from the heart. And proper conju--conjugation. */
129 | /* Hang on, Rick. Aren't there, like, you know...a bunch of words that might
130 | end with those letters, but a-aren't--*/
131 | /* You already lost me, Morty. I'm over here sn--I'm sitting...over here, snoring...
132 | over here, already, because of what you just said. And are you kidding me, Morty?
133 | This from YOU? Can you even, I dunno, even write your own name? The answer is
134 | I don't have the time OR the patience to catch all the exc-exceptions. You gotta
135 | look at the big picture, Morty. */
136 | /* Oh man, Rick, okay... */
137 | wordToSquanch = wordToSquanch.toLowerCase();
138 | if (unsquanchables.indexOf(wordToSquanch) > -1 || wordToSquanch.match(escapedHTMLRegex))
139 | isSquanchable = false;
140 | else if (wordToSquanch.substr(wordToSquanch.length - 3, 3) === "ing" && ingExceptions.indexOf(wordToSquanch) === -1)
141 | squanchText += "ing";
142 | else if (wordToSquanch.substr(wordToSquanch.length - 2, 2) === "ly" && lyExceptions.indexOf(wordToSquanch) === -1)
143 | squanchText += "ly";
144 | else if (wordToSquanch.substr(wordToSquanch.length - 2, 2) === "es" || wordToSquanch.slice(-1) === "s")
145 | squanchText += "es";
146 | else if (wordToSquanch.substr(wordToSquanch.length - 2, 2) === "ed")
147 | squanchText += "ed";
148 |
149 |
150 | // This is where the magic happens, baby. Squanchy would be proud.
151 | // Okay, all right, looks like we're--looks like we're just about done, huh?
152 | /* Just about, Morty. Those little bastards are really gonna wet themselves
153 | when they get their hands on this, Morty. They'll be in...in the palms of
154 | our...hands. */
155 | if (isSquanchable) {
156 | if (isAllCaps)
157 | squanchText = squanchText.toUpperCase();
158 |
159 | unSquanchedWords[j] = unSquanchedWords[j].replace(replacementRegex, squanchText);
160 | }
161 | }
162 | }
163 |
164 | // See, Morty? No one even noticed. You little piece of shit.
165 | /* Y-you know what, Rick? I'm getting real sick of you always taking a big,
166 | a big shit over my feelings, you know? I'm over here, slaving over the...working
167 | on this big file with you, and I don't even know what...like, you know, programming
168 | is, and you're giving me the, the, the, the business about it? You're a real piece of
169 | work Rick, just a...a real, nice...handcrafted, homebr--homemade asshole. Homebrewed,
170 | is...what I was looking for, uh...back there. */
171 | /* Speaking of which, Morty, while you were bitching about nothing back there, I was--URNGHH
172 | --thinking you could-- */
173 | /* Don't say it, Rick. */
174 | /* --thinking you could make yourself useful and fetch me another homebr-- */
175 | /* That is IT, Rick! I've had it. You know? I'm throwing in the towel, Rick.
176 | I'm throwing in the cards. Cashing in the...cashing in the chips. I'm out of here, Rick. */
177 | var joinerString = " ";
178 | if (possibleLinks) {
179 | for (j = 0; j < possibleLinks.length; j++) {
180 | unSquanchedWords[unSquanchedWords.indexOf("")] = possibleLinks[j];
181 | }
182 | // A specific case that pops up do to the regex not perfectly handling
183 | // selector texts that are couched in parentheses
184 | if (unSquanchedWords.length === 2 && unSquanchedWords[0] === "(" && unSquanchedWords[1] === ")") {
185 | unSquanchedWords = ["(", possibleLinks, ")"];
186 | joinerString = "";
187 | }
188 | }
189 |
190 | /* Little...little punk-ass bitch doesn't know what he's missing. Because the Squanchifier
191 | IS GOING TO BE MY GREATEST WORK OF ALL TIME AND YOU COULD HAVE BEEN A PART OF IT, YOU--*/
192 | // Dad, why are you yelling from the garage?
193 | // Huh? Oh, it--nothing, Sweetie.
194 | // Rick, I distinctly remember asking you to keep it down while the glue is drying, or el--
195 | /* Or else WHAT, JERRY? Do you seriously think anyone gives a shit about your ship-in-a-fucking-bottle
196 | collection? I give so little of a shit that it's negative--I TAKE shit about it. By that logic I should
197 | ask Morty for the rest of the whiny shit he was giving me earlier just so that the equation balances out.
198 | I know it's natural to wanna protect the bottle containing literally the only liter of space in the
199 | universe where YOU control ANYTHING, Jerry, but you seem to forget that everything outside of it is mine.
200 | So, uhhh...whoopsie.*/
201 | // Oh my God, oh my God, Rick!
202 | // Dad!
203 | // Oh, sorry Jerry, I'll buy you a new one. You know, from a ten-year-old kid who did ten times as good a job.
204 | squanchedWords = unSquanchedWords.join(joinerString);
205 | DOMElements[i].innerHTML = squanchedWords.trim();
206 | }
207 | }
208 | });
209 | };
210 |
211 | // That is the question.
212 | var toSquanchOrNotToSquanch = function() {
213 |
214 | // They downloaded the extension. They knew what they were getting themselves
215 | // into.
216 | var defaultActivated = true;
217 |
218 | // grab the local storage value for if squanching is activated
219 | chrome.storage.local.get('activated', function(data) {
220 |
221 | // If they've never used it before, set the storage value.
222 | // Why check against those values explicitly? We want to obey the value
223 | // when it's false, which is, surprisingly, a falsey value.
224 | if (data.activated === undefined || data.activated === null) {
225 | data.activated = defaultActivated;
226 | chrome.storage.local.set({"activated": data.activated});
227 | }
228 | if (data.activated) {
229 | // Gotta fall back to something if they've never squanched before, Morty.
230 | var defaultSquanchiness = 0.95;
231 |
232 | // grab the local storage value for squanchiness
233 | chrome.storage.local.get('squanchiness', function(data) {
234 | if (!data.squanchiness) {
235 | data.squanchiness = defaultSquanchiness;
236 | chrome.storage.local.set({"squanchiness": data.squanchiness});
237 | }
238 | squanchify(data.squanchiness);
239 | });
240 | }
241 | });
242 | }
243 |
244 | // Like I'm really gonna use the whole underscore lib for this.
245 | var debounce = function(func, wait, immediate) {
246 | var timeout;
247 | return function() {
248 | var context = this, args = arguments;
249 | var later = function() {
250 | timeout = null;
251 | if (!immediate) func.apply(context, args);
252 | };
253 | var callNow = immediate && !timeout;
254 | clearTimeout(timeout);
255 | timeout = setTimeout(later, wait);
256 | if (callNow) func.apply(context, args);
257 | };
258 | };
259 |
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 2,
3 |
4 | "name": "Squanchify",
5 | "description": "This extension makes your browsing experience...Squanchier.",
6 | "version": "1.4",
7 |
8 | "permissions": [
9 | "activeTab",
10 | "storage",
11 | "https://ajax.googleapis.com/"
12 | ],
13 |
14 | "background": {
15 | "scripts": ["js/jquery.min.js","js/background.js"]
16 | },
17 |
18 | "browser_action": {
19 | "default_popup": "howSquanchy.html"
20 | },
21 |
22 | "icons": { "16": "icons/squanchy-16.png",
23 | "48": "icons/squanchy-48.png",
24 | "128": "icons/squanchy-128.png" },
25 |
26 | "content_scripts": [
27 | {
28 | "matches": [""],
29 | "css": ["squanchyStyle.css"],
30 | "js": ["js/jquery.min.js","js/squanchify.js"]
31 | }
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/screenshots/CNNSquanch.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nichite/squanchify/28c8991b3960cdc46df0e422f4f991c1db14ed72/screenshots/CNNSquanch.PNG
--------------------------------------------------------------------------------
/screenshots/ChromeSquanch.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nichite/squanchify/28c8991b3960cdc46df0e422f4f991c1db14ed72/screenshots/ChromeSquanch.PNG
--------------------------------------------------------------------------------
/screenshots/RedditSquanch.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nichite/squanchify/28c8991b3960cdc46df0e422f4f991c1db14ed72/screenshots/RedditSquanch.PNG
--------------------------------------------------------------------------------
/screenshots/SquanchyPopup.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nichite/squanchify/28c8991b3960cdc46df0e422f4f991c1db14ed72/screenshots/SquanchyPopup.PNG
--------------------------------------------------------------------------------
/squanchyStyle.css:
--------------------------------------------------------------------------------
1 | .squanchy-container {
2 | padding-left: 10px;
3 | padding-right: 10px;
4 | width: 225px;
5 | }
6 |
7 | .slider-container {
8 | height: 50%;
9 | display: none;
10 | }
11 |
12 | .squanchiness-prompt {
13 | font-size: 12pt;
14 | }
15 |
16 | .squanchy-slider {
17 | width: 100%;
18 | -webkit-appearance: none;
19 | align-content: center;
20 | }
21 |
22 | .squanchy-slider::-webkit-slider-runnable-track {
23 | width: inherit;
24 | height: 5px;
25 | background: #ddd;
26 | border: none;
27 | border-radius: 3px;
28 | margin: 10px;
29 | }
30 |
31 | .squanchy-slider::-webkit-slider-thumb {
32 | -webkit-appearance: none;
33 | border: none;
34 | height: 16px;
35 | width: 16px;
36 | border-radius: 50%;
37 | background: goldenrod;
38 | margin-top: -4px;
39 | cursor: pointer;
40 | }
41 |
42 | .squanchy-slider:focus {
43 | outline: none;
44 | }
45 |
46 | .squanchy-slider:focus::-webkit-slider-runnable-track {
47 | background: #ccc;
48 | }
49 |
50 | .squanchy-button {
51 | position: relative;
52 | margin-top: 15px;
53 | margin-bottom: 10px;
54 | vertical-align: top;
55 | width: 100%;
56 | height: 60px;
57 | padding: 0;
58 | font-size: 14pt;
59 | color: white;
60 | text-align: center;
61 | text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
62 | background: goldenrod;
63 | border: 0;
64 | cursor: pointer;
65 | }
66 |
67 | .squanchy-button:focus {
68 | outline: 0 solid transparent;
69 | }
70 |
--------------------------------------------------------------------------------