Interesting Wikipedia userscript

Does evil things to wikipedia articles

当前为 2024-08-21 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Interesting Wikipedia userscript
  3. // @namespace roxwize
  4. // @match *://*.wikipedia.org/*
  5. // @grant none
  6. // @version 1.5.3
  7. // @author roxwize
  8. // @description Does evil things to wikipedia articles
  9. // @license GPL-3.0-or-later
  10. // @homepageURL https://greasyfork.org/en/scripts/479665-interesting-wikipedia-userscript
  11. // ==/UserScript==
  12.  
  13. class Keymap {
  14. constructor(displayName, keys) {
  15. this._name = displayName;
  16. this.keys = keys.split(" ").map((e) => e.split(""));
  17. this.repeated = false;
  18. }
  19.  
  20. next() {
  21. if (this.x != undefined && this.y != undefined) {
  22. if (Math.random() >= 0.5) this.x = this.x === this.keys[this.y].length - 1 ? 0 : this.x + 1;
  23. else {
  24. this.y = this.y === this.keys.length - 1 ? 0 : this.y + 1;
  25. if (this.x >= this.keys[this.y].length) this.x = this.keys[this.y].length - 1;
  26. }
  27. // chance to repeat
  28. if (Math.random() <= 0.2 && !this.repeated) {
  29. this.repeated = true;
  30. return this.next();
  31. } else this.repeated = false;
  32. } else {
  33. this.y ??= Math.floor(Math.random() * this.keys.length);
  34. this.x ??= Math.floor(Math.random() * this.keys[this.y].length);
  35. }
  36. return this.keys[this.y][this.x];
  37. }
  38. }
  39.  
  40. const keymaps = [
  41. new Keymap("QWERTY", "qwertyuiop asdfghjkl zxcvbnm"),
  42. new Keymap("AZERTY", "azertyuiop qsdfghjklm wxcvbn"),
  43. new Keymap("Dvorak", "pyfgcrl aoeuidhtns qjkxbmwvz"),
  44. new Keymap("Colemak", "qwfpgjluy arstdhneio zxcvbkm"),
  45. new Keymap("Workman", "qdrwbjfup ashtgyneoi zxmcvkl")
  46. ];
  47.  
  48. const images = [
  49. "https://media.tenor.com/MBkt9DXPaUYAAAAd/ddostumka%C3%A7.gif",
  50. "https://media.tenor.com/C8aEDgYC1y4AAAAd/aphex-twin-come-to-daddy.gif",
  51. "https://media.tenor.com/4i00_7OrisUAAAAC/sandoz-canu-sandoz.gif",
  52. "https://media.tenor.com/hrNDlz8yD3UAAAAC/harley-quinn-margot-robbie.gif",
  53. "https://media.tenor.com/s1w-Sc5ahpEAAAAd/paz-pazzin.gif",
  54. "https://media.tenor.com/dWS427mpAZAAAAAd/secu-rity-meme.gif",
  55. "https://media.tenor.com/XUFDsSt48GYAAAAd/eminem.gif",
  56. "https://media.tenor.com/QgphpoWrjaAAAAAd/retro-retro-dev.gif",
  57. "https://media.tenor.com/uSo4lQu9dVgAAAAC/homer-smile.gif",
  58. "https://media.tenor.com/QMpyBmPBlhoAAAAC/wtf-roblox.gif",
  59. "https://media.tenor.com/47hdAGX-uAwAAAAC/charjabug-weegee.gif",
  60. "https://media.tenor.com/HcQ44DFmPccAAAAC/video-gaming.gif",
  61. "https://media.tenor.com/79djON9nNhMAAAAC/0001.gif",
  62. "https://media.tenor.com/U2ilbVQ-DAwAAAAC/jameis-winston-crab.gif",
  63. "https://c.tenor.com/jZlLTydic2UAAAAd/tenor.gif",
  64. "https://c.tenor.com/KE0dcwJ1VS4AAAAC/tenor.gif",
  65. "https://media1.tenor.com/m/cmiHJgTxV5AAAAAd/minccino-poketoon.gif",
  66. "https://media1.tenor.com/m/klfhGWhyzzYAAAAd/praise-allah.gif",
  67. "https://media1.tenor.com/m/TiJaOnPTFTsAAAAC/williams-evil.gif",
  68. "https://media1.tenor.com/m/sUey3ekTfDoAAAAC/slugcat-rain-world-artificer-dance.gif",
  69. "https://media1.tenor.com/m/gfZaN-s9gm0AAAAd/tsg-hoffenheim-fussball.gif",
  70. "https://media1.tenor.com/m/8fkcv1WDDM0AAAAC/robot-hello.gif",
  71. "https://media1.tenor.com/m/mMhU45-pZGsAAAAd/autechre-sean-booth.gif",
  72. "https://media1.tenor.com/m/I3wc0IZXfqYAAAAC/benedict-cumberbatch-doctor-strange.gif",
  73. "https://media1.tenor.com/m/D8GSu_9yYmAAAAAC/urkel-steve-urkel.gif",
  74. "https://media1.tenor.com/m/E2xaet0TtYsAAAAd/south-park-block13.gif",
  75. "https://media1.tenor.com/m/i9Ge9uKBVAcAAAAC/exorcist-prank.gif",
  76. "https://media1.tenor.com/m/1_JQdzkUcqQAAAAd/pepto-drink.gif",
  77. "https://media1.tenor.com/m/aRaj8_BOr4IAAAAC/philip-wikipedia.gif",
  78. "https://media1.tenor.com/m/jIEjhVJPlrsAAAAd/hitman-hitman2.gif",
  79. "https://media1.tenor.com/m/Vw16aqm7wiEAAAAd/rhythm-heaven-fail.gif",
  80. "https://media1.tenor.com/m/IQcO08GxscoAAAAd/smooth-criminal-cat.gif",
  81. "https://media1.tenor.com/m/BuXXCcVsbmcAAAAd/bogdan-moment-hl.gif",
  82. "https://media1.tenor.com/m/BImhqpdSqUUAAAAd/evil-villain.gif",
  83. "https://media1.tenor.com/m/iDbMu5kjwrkAAAAd/man-runnin.gif",
  84. "https://media1.tenor.com/m/hHwMQpLGCcQAAAAd/kermit-gay-kermit-potion.gif",
  85. "https://media1.tenor.com/m/T850EkA3rgMAAAAC/112hageland-leuven2.gif",
  86. "https://media1.tenor.com/m/rp8l7QTPjbMAAAAd/coca-cola-coke.gif",
  87. "https://media1.tenor.com/m/HL5dPXaDcgYAAAAC/din-barbaad.gif",
  88. "https://media1.tenor.com/m/wpaGL3wIw4kAAAAC/caprisun.gif",
  89. "https://media1.tenor.com/m/XBrPEFm-_14AAAAC/cat-lightning.gif",
  90. "https://media1.tenor.com/m/PsgKlEP-1PgAAAAd/creepy-minecraft.gif",
  91. "https://media1.tenor.com/m/LsGpcwpSsmoAAAAC/googliness-the-internship.gif",
  92. "https://media1.tenor.com/m/J7-lKCV1jjQAAAAd/fat-guy.gif",
  93. "https://media1.tenor.com/m/0rc0l8Qqx-kAAAAd/penguin.gif",
  94. "https://media1.tenor.com/m/ggtuNDdcGO0AAAAC/object-fool-eucerin.gif",
  95. "https://media1.tenor.com/m/cG7XQuWtkekAAAAC/link-counsciousness.gif",
  96. "https://media1.tenor.com/m/ZvPv7jkHXd8AAAAC/object-fool-eucerin.gif",
  97. "https://media1.tenor.com/m/m4Fy2lQd5j0AAAAC/trisha-tamil.gif",
  98. "https://media1.tenor.com/m/53ff8yADDDcAAAAC/arthritis-inflammation.gif",
  99. "https://media1.tenor.com/m/TxTQBaxnGwgAAAAC/bird-brain-mechanical.gif",
  100. "https://media1.tenor.com/m/rYscw0R2NqEAAAAC/mario-retro.gif",
  101. "https://media1.tenor.com/m/821Jm-bIScoAAAAd/dance-robot.gif",
  102. "https://media1.tenor.com/m/u_J8-0ocXfMAAAAC/homer-homer-simpson.gif",
  103. "https://media1.tenor.com/m/d7RH_KsFTWQAAAAd/five-nights-at-freddy%27s-fnaf.gif",
  104. "https://media1.tenor.com/m/6tJ8-Vu_CWQAAAAC/patapon-patapon3.gif",
  105. "https://media1.tenor.com/m/vRxgL6nyzK0AAAAd/dancing-3d.gif",
  106. "https://media1.tenor.com/m/s8mYduoNxQAAAAAC/home-alone-december.gif",
  107. "https://media1.tenor.com/m/H0TP37zS6j4AAAAC/pizza-tower-the-noise.gif",
  108. "https://media1.tenor.com/m/nnQsqX9g_YYAAAAd/tang916-happy-easter.gif",
  109. "https://media1.tenor.com/m/uCZPKgq0jDYAAAAC/ljarius-sneed-ljarius.gif",
  110. "https://media1.tenor.com/m/I-hb4OExuugAAAAC/bfdi-mouth.gif",
  111. "https://media1.tenor.com/m/s-7ru8cGJU0AAAAd/caveira-skull.gif",
  112. "https://media1.tenor.com/m/8NRi6VMAbR8AAAAC/bunny-maloney-jean-francois.gif",
  113. "https://media1.tenor.com/m/kBCP0yD9sVYAAAAd/thom-yorke-walking.gif",
  114. "https://media1.tenor.com/m/iNoVG4ZlXwUAAAAC/gta.gif",
  115. "https://media1.tenor.com/m/4H_vBUFCuEgAAAAd/skate-glitch.gif",
  116. "https://media1.tenor.com/m/MnKaoweSL7YAAAAd/sneed-bop.gif",
  117. "https://media1.tenor.com/m/e71nId8Yj4kAAAAd/shenmue-shenmue-forklift.gif",
  118. "https://media1.tenor.com/m/3-w0dE_SL7UAAAAC/o2-o2robot.gif",
  119. "https://media1.tenor.com/m/TPSxhmp-6lkAAAAC/roblox.gif",
  120. "https://media1.tenor.com/m/A4bTak1BWbgAAAAd/scolex-fish.gif",
  121. "https://media1.tenor.com/m/k0pf_TDz1DsAAAAd/aphextwin-idm.gif",
  122. "https://media1.tenor.com/m/ZetHEGNctWcAAAAd/click-here-to-upload-to-tenor-upload-your-own-gifs.gif",
  123. "https://media1.tenor.com/m/-7EhZTjdRQ8AAAAC/android-running-android.gif",
  124. "https://media1.tenor.com/m/CtgzUsEujTsAAAAC/sistersmoi-siss.gif",
  125. "https://media1.tenor.com/m/mMhU45-pZGsAAAAd/autechre-sean-booth.gif",
  126. "https://media1.tenor.com/m/wY95uJQ4DYoAAAAC/popsticky-popcorn-ab.gif",
  127. // thankyou to ellis for the gifs
  128. "https://64.media.tumblr.com/1a35ba4b9cc154ea6a1f7b323a817e9d/57edb24c0e90f3d4-92/s1280x1920/a2e0cf8398860a0e401e24d7560925f78be40d61.gif",
  129. "https://media1.tenor.com/m/LzikZYfpDwAAAAAC/sewing-sewing-machine.gif",
  130. "https://media1.tenor.com/m/hweQnVtO6UMAAAAC/spongebob-wall.gif",
  131. "https://media1.tenor.com/m/TVeq1AOlHQAAAAAC/bubsy-explode.gif",
  132. // thankyou to me for the gifs
  133. "https://media1.tenor.com/m/a0aS96FfutgAAAAd/radiohead-thom-yorke.gif",
  134. "https://media1.tenor.com/m/RCntpOKN4bQAAAAd/erm-what-the-sigma-sigma.gif",
  135. "https://media1.tenor.com/m/6CIKiVAesy0AAAAC/pubie-fulptube.gif",
  136. "https://media1.tenor.com/m/7peLhQT7GrcAAAAC/wacky-silly.gif",
  137. "https://media1.tenor.com/m/kw-zE0H3lSgAAAAC/wooper-roller-skates.gif",
  138. "https://media1.tenor.com/m/1BlDMUTDCZ4AAAAC/sackboy-little-big-planet.gif",
  139. "https://media1.tenor.com/m/y0Yub_nVmNYAAAAd/jerma-jerma985.gif",
  140. "https://media1.tenor.com/m/GnrqZuKrwzcAAAAC/snoop-dogg.gif",
  141. "https://media1.tenor.com/m/YyjJWH0YMxoAAAAd/william-shakespeare-shakespeare.gif",
  142. "https://media1.tenor.com/m/PBz8WbWestUAAAAC/dive-toilet.gif",
  143. "https://media1.tenor.com/m/bV6ObqR_dREAAAAC/rage-3kliksphilip.gif",
  144. "https://media1.tenor.com/m/sO8QSSzBXhkAAAAC/radiohead-bear.gif",
  145. "https://media1.tenor.com/m/ivG0cBBNSdMAAAAC/evil-bfdi.gif",
  146. "https://media1.tenor.com/m/dXAnXprr_h4AAAAC/morgana-persona-5.gif",
  147. "https://media1.tenor.com/m/SNKFpcrFWWAAAAAC/persona-5-morgana.gif",
  148. "https://media1.tenor.com/m/qFaVryk8_64AAAAC/morgana-dance-morgana.gif",
  149. "https://media1.tenor.com/m/a3gIxxiyctMAAAAC/persona5-morgana.gif",
  150. // thankyou to jack for the gifs
  151. "https://media1.tenor.com/m/cjefIM5Y6KsAAAAd/the-orville-36-hours.gif",
  152. "https://media1.tenor.com/m/V3MyGNQiaEIAAAAC/dancing-twerk.gif",
  153. "https://media1.tenor.com/m/fwoJNI_CpjQAAAAC/skeleton-shocked.gif",
  154. "https://media1.tenor.com/m/SiJels-VZLkAAAAC/terminator-arnold-schwarzenegger.gif",
  155. "https://media1.tenor.com/m/XuT_ifWR91wAAAAC/rage-mad.gif",
  156. "https://media.tenor.com/qzA2L1B7nP0AAAAM/cali007.gif",
  157. "https://media1.tenor.com/m/8vQY3QJX_soAAAAC/andy-exhausted.gif",
  158. "https://media1.tenor.com/m/JHCBI26vkJIAAAAC/alien-alien-dance.gif",
  159. "https://media1.tenor.com/m/G2Hgohh0P-8AAAAC/jay-z-shot.gif",
  160. "https://media1.tenor.com/m/OFl-Kxj_D_8AAAAd/smart-iptv-iptv.gif",
  161. "https://media1.tenor.com/m/aqNxzTht6IAAAAAC/cat-fire.gif",
  162. "https://media1.tenor.com/m/HtFYNC0gUIEAAAAC/cave-story-sue-sakamoto.gif",
  163. "https://media1.tenor.com/m/AqG3VVVxwYMAAAAC/arvinguy.gif",
  164. "https://media1.tenor.com/m/ZBSAJsozOmwAAAAC/chinese-restaurant-in-the-future-never-let-you-finish-your-sentence.gif"
  165. ];
  166. const imageWhitelist = new Array(images.length).fill(-1).map((_, i) => i);
  167. const style = `
  168. #god{position:fixed;bottom:1em;left:1em;background:rgba(50,40,80,0.8);padding:1em;color:white;}
  169. #gantzgraf{position:fixed;bottom:1em;right:1em;background:rgba(50,40,80,0.8);padding:1em;color:white;text-align:right;}
  170. #gantzgraf .option{display:flex;align-items:center;gap:1em;}
  171. #gantzgraf .option label{flex-grow:1;text-align:right;}
  172. #giflist-root{position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(245,248,242,0.85);padding:1rem;overflow-y:auto;box-sizing:border-box;}
  173. #giflist-root-header{height:10%;border-bottom:1px solid rgba(0,0,0,0.2);overflow-x:hidden;margin-bottom:1rem;}
  174. #giflist-root-header h1{font-size:300%;border-bottom:0;margin:0;font-weight:bold;}
  175. #giflist-root-list{display:grid;grid-template-columns:1fr 1fr 1fr 1fr 1fr 1fr;grid-auto-rows:minmax(120px,1fr);gap:2%;}
  176. #giflist-root-list div{display:flex;align-items:center;justify-content:center;background-color:rgba(255,255,255,0.7);border:1px solid rgba(0,0,0,0.25);border-radius:10px;padding:6px;}
  177. #giflist-root-list div:hover{background-color:rgba(180,180,180,0.7);cursor:pointer;}
  178. #giflist-root-list div img{width:80%;max-height:80%;}
  179. #giflist-root-list div:hover img{filter:grayscale(1);}
  180. span.small{display:block;font-size:smaller;}
  181. span.sub{display:block;color:rgba(0,0,0,0.7);font-style:italic;}
  182. .iwusbox a{color:white;font-weight:bold;text-decoration:underline;}
  183. `;
  184. let words = [];
  185.  
  186. const config = {
  187. styleModifications: {
  188. label: "Modify page style",
  189. current: false
  190. },
  191. linkModifications: {
  192. label: "Modify links",
  193. current: true
  194. },
  195. figCaptions: {
  196. label: "Modify image captions",
  197. current: false
  198. },
  199. imageModifications: {
  200. label: "Modify images",
  201. current: true
  202. },
  203. textualModifications: {
  204. label: "Screw up text nodes",
  205. current: true
  206. },
  207. excessive: {
  208. label: "<b>Overdrive</b>",
  209. current: true
  210. },
  211. randomLinks: {
  212. label: "Change links to be random",
  213. current: false
  214. },
  215. keymap: {
  216. label: "Keysmash layout",
  217. current: 0,
  218. vals: keymaps
  219. }
  220. };
  221.  
  222. function modify(e, f) {
  223. const n = e.childNodes;
  224. for (let d of n) {
  225. if (d.nodeType === Node.TEXT_NODE) f(d);
  226. else modify(d, f);
  227. }
  228. }
  229.  
  230. const chance = () => Math.random() * 100;
  231. const rand = (a) => a[Math.floor(Math.random() * a.length)];
  232. const screwup = (str) => {
  233. const s = str.split("");
  234. let o = "";
  235. let i = 0;
  236. for (let l of s) {
  237. if (chance() > 60) continue;
  238. if (chance() < 20 && s[i+1]) o += s[i+1];
  239. if (chance() > 80 && s[i-1]) o += s[i-1];
  240. if (chance() < 80) o += l;
  241. if (chance() > 90) o += l;
  242. i++;
  243. }
  244. return o;
  245. }
  246. const applyRandomTransformation = (node, transformation, chance = 0.2) => {
  247. const chars = [];
  248. for (let i = 0; i < node.textContent.length; i++) {
  249. let c = node.textContent[i];
  250. if (Math.random() < chance) {
  251. c = transformation(c);
  252. }
  253. chars.push(c);
  254. }
  255. return chars.join("");
  256. }
  257. const applyRandomWordTransformation = (node, transformation, chance = 0.2) => {
  258. const words = node.textContent.split(" ");
  259. for (let i in words) {
  260. if (Math.random() < chance) words[i] = transformation(words[i]);
  261. }
  262. return words.join(" ");
  263. }
  264.  
  265. (function() {
  266. // Add userscript styles
  267. const stylesheet = document.createElement("style");
  268. stylesheet.innerHTML = style;
  269. document.head.appendChild(stylesheet);
  270. // Root element.
  271. const rootEl = document.createElement("div");
  272. rootEl.id = "god";
  273. rootEl.classList.add("iwusbox");
  274. rootEl.innerHTML = `<span class="small">iwus v${GM.info.script.version} | <a href="https://greasyfork.org/en/scripts/479665-interesting-wikipedia-userscript" data-immune="true">greasyfork</a></span><input type="text" id="bregex" placeholder="regex" /><br/><input type="text" id="breplacement" placeholder="replacement" /><br/><button id="bok" style="cursor:pointer;">ok</button>`;
  275. document.body.appendChild(rootEl);
  276. document.getElementById("bok").addEventListener("click", () => {
  277. // Begin
  278. words = [];
  279. const regexp = new RegExp(document.getElementById("bregex").value, "g");
  280. const replce = document.getElementById("breplacement").value;
  281. const chchrs = ["桤","酒","垄","耐","撑","澉","颎","苦","耗","檎","霰","嗲","扩","京","柩","辨","蒿","蠓","湟","药","更","哇","迕","烬","陪","坭","摘","罹","徙","脖","溶","佬","岣","桅","看","缎"];
  282. const puncts = [" ? ", " ! ", " ?? ", " !! ", " ?! ", " !? ", "... "]
  283. const phrase = ["Chinese restaurant in the future never let you finish your sentence", "Chinese restaurant in the future", "never let you finish your sentence", "Lego Island"];
  284. // new Array(93).fill("").map((e, i) => String.fromCharCode(i + 33));
  285. const asciic = ["!","\"","#","$","%","&","'","(",")","*","+",",","-",".","/","0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?","@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^","_","`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","|","}"];
  286. const keylyt = keymaps[config.keymap.current];
  287. document.querySelectorAll(`p, ${config.figCaptions.current ? "figcaption," : ""} th, td, li, h1, h2, h3, h4, h5, h6, dd`).forEach((e) => {
  288. modify(e, (node) => {
  289. node.textContent = node.textContent.replaceAll(regexp, replce);
  290. if (node.textContent.length > 2 && node.textContent !== ".") words.push(node.textContent);
  291. // == TEXTUAL MODIFICATIONS == //
  292. if (config.textualModifications.current) {
  293. if (config.excessive.current) {
  294. if (chance() > 90) {
  295. // 10% chance to remove all vowels and scramble
  296. node.textContent = screwup(node.textContent.replaceAll(/[aeiou]/g, ""));
  297. } else if (chance() > 90) {
  298. // 10% chance to scramble normally otherwise
  299. node.textContent = screwup(node.textContent);
  300. }
  301. // replace all punctuation with random in list or append to a given character with 20% chance
  302. node.textContent = applyRandomTransformation(node, (c) => {
  303. if (["!", "?", "."].includes(c) || Math.random() > 0.8) {
  304. return rand(puncts);
  305. }
  306. });
  307. }
  308. // [jack idea no.1] 50% chance for commas to repeat 5 to 10 times
  309. node.textContent = applyRandomTransformation(node, (c) => {
  310. if (c === ',' && Math.random() >= 0.5) {
  311. return new Array(Math.floor(Math.random() * 5) + 5).fill(",").join("");
  312. }
  313. });
  314. // [jack idea no.2] 5% chance for the computer to mash its keyboard 5 to 35 times
  315. if (Math.random() <= 0.05 && config.excessive.current) {
  316. let s = "";
  317. for (let i = 0; i < Math.floor(Math.random() * 5) + 30; i++)
  318. s += keylyt.next();
  319. node.textContent = s + node.textContent;
  320. }
  321. // 1% chance to add a random word
  322. node.textContent = applyRandomWordTransformation(node, (w) => rand(phrase), 0.01);
  323. // 90% chance to just get cut off after ten letters at a random point
  324. if (node.textContent.length > 10 && Math.random() > 0.1 && config.excessive.current) {
  325. node.textContent = node.textContent.substring(0, Math.floor(Math.random() * (node.textContent.length - 10)) + 10)
  326. }
  327. // 60% chance to make random letters uppercase with a 20% chance for each
  328. if (chance() > 60) {
  329. node.textContent = applyRandomTransformation(node, (c) => c.toUpperCase());
  330. }
  331. // 10% chance to add anywhere from 5 to 85 random chinese characters after a word
  332. if (Math.random() > 0.9 && config.excessive.current) {
  333. for (let i = 0; i < Math.floor(Math.random() * 80) + 5; i++) {
  334. node.textContent += rand(chchrs);
  335. }
  336. }
  337. }
  338. });
  339. // == STYLE MODIFICATIONS == //
  340. if (config.styleModifications.current) {
  341. e.style.color = `hsl(${Math.round(Math.random()*360)} 50% 50%)`;
  342. if (chance() > 75) e.style.backgroundColor = `hsl(${Math.round(Math.random()*360)} 50% 50%)`;
  343. e.style.textDecoration = chance() > 70 ? "underline" : "normal";
  344. e.style.fontStyle = chance() > 70 ? "italic" : "normal";
  345. if (chance() > 30) {
  346. e.style.transform = `translate(${Math.random()*25}px, ${Math.random()*50}px)`;
  347. } else {
  348. e.style.transform = `rotate(${Math.random()*5-2.5}deg)`;
  349. if (chance() > 45) {
  350. e.style.transform += ` scale(${Math.random()*2+0.5})`;
  351. }
  352. }
  353. e.style.fontSize = `${9 + Math.floor(Math.random()*10)}pt`;
  354. }
  355. });
  356. if (config.imageModifications.current) {
  357. document.querySelectorAll("img").forEach((e) => {
  358. e.src = images[rand(imageWhitelist)];
  359. });
  360. }
  361. // == LINK MODIFICATIONS == //
  362. if (config.linkModifications.current) {
  363. document.querySelectorAll("a").forEach((e) => {
  364. if (e.dataset.immune === "true") return;
  365.  
  366. if (config.randomLinks.current) {
  367. e.setAttribute("href", "https://en.wikipedia.org/wiki/Special:Random");
  368. }
  369. modify(e, (node) => {
  370. node.textContent = rand(words);
  371. });
  372. });
  373. }
  374. });
  375. // Config options
  376. const configEl = document.createElement("div");
  377. configEl.id = "gantzgraf";
  378. configEl.classList.add("iwusbox");
  379. for (let [k, v] of Object.entries(config)) {
  380. const e = document.createElement("div");
  381. e.classList.add("option");
  382. e.innerHTML = `<label for="bo-${k}">${v.label}</label>`;
  383. let o;
  384. if (typeof v.current === "number" && v.vals != undefined) {
  385. // o = document.createElement("div");
  386. // o.style = "display:block;"
  387. // v.vals.forEach((el, i) => {
  388. // const vO = document.createElement("input");
  389. // vO.type = "radio";
  390. // vO.name = `bo-${k}`;
  391. // vO.id = `ro-${k}-${i}`;
  392. // vO.value = i.toString();
  393. // o.appendChild(vO);
  394. // const vL = document.createElement("label");
  395. // vL.setAttribute("for", vO.id);
  396. // vL.innerHTML = el;
  397. // vL.style.display = "block";
  398. // o.appendChild(vL);
  399. // });
  400. o = document.createElement("select");
  401. v.vals.forEach((e, i) => {
  402. const vO = document.createElement("option");
  403. vO.value = i;
  404. vO.innerHTML = typeof e === "object" ? e._name : e;
  405. o.appendChild(vO);
  406. });
  407. o.addEventListener("input", () => {
  408. config[k].current = Number(o.value);
  409. })
  410. } else {
  411. o = document.createElement("input");
  412. o.type = "checkbox";
  413. o.checked = config[k].current;
  414. o.addEventListener("input", () => {
  415. config[k].current = o.checked;
  416. });
  417. }
  418. o.name = `bo-${k}`;
  419. o.id = o.name;
  420. e.appendChild(o);
  421. configEl.appendChild(e);
  422. }
  423. // Giflist opener
  424. const openGifListLink = document.createElement("a");
  425. openGifListLink.innerHTML = "open the gif list";
  426. openGifListLink.href = "javascript:void(0);"
  427. openGifListLink.onclick = renderGifList;
  428. openGifListLink.dataset.immune = true;
  429. configEl.appendChild(openGifListLink);
  430. document.body.appendChild(configEl);
  431. })();
  432.  
  433. // Maybe run automatically on page load
  434. function renderGifList() {
  435. // Root div
  436. const rootDiv = document.createElement("div");
  437. rootDiv.id = "giflist-root";
  438. rootDiv.innerHTML = `
  439. <div id="giflist-root-header">
  440. <h1>Giflist</h1><span class="sub">Click on a gif to remove it | <a href="javascript:document.getElementById('giflist-root').remove()" data-immune="true">close</a></span>
  441. </div>
  442. `;
  443. const rootList = document.createElement("div");
  444. rootList.id = "giflist-root-list";
  445. // Individual gif elements
  446. let i = 0;
  447. for (let gif of images) {
  448. const gifDiv = document.createElement("div");
  449. gifDiv.id = `iwusdiv-${i}`;
  450. gifDiv.dataset.index = i;
  451. gifDiv.innerHTML = `<img src="${gif}" alt="no.${i}">`;
  452. gifDiv.addEventListener("click", () => {
  453. if (imageWhitelist.length === 1) {
  454. alert("No");
  455. return;
  456. }
  457. imageWhitelist.splice(imageWhitelist.indexOf(parseInt(gifDiv.dataset.index)), 1);
  458. gifDiv.remove();
  459. });
  460. rootList.appendChild(gifDiv);
  461. i++;
  462. }
  463. rootDiv.appendChild(rootList);
  464. document.body.appendChild(rootDiv);
  465. }