diff --git a/4chan.org/4c-autohide.js b/4chan.org/4c-autohide.js
new file mode 100644
index 0000000..53e7d91
--- /dev/null
+++ b/4chan.org/4c-autohide.js
@@ -0,0 +1,22 @@
+// ==UserScript==
+// @name 4c-autohide
+// @description Keyword based thread hider
+// @author ae
+// @namespace Violentmonkey Scripts
+// @match *://boards.4chan*.org/*/catalog
+// @version 1.0
+// ==/UserScript==
+
+window.addEventListener("load", () => {
+ const keywords = [] // e.g. ["/sdg/", "luke smith"]
+ const data = document.getElementsByClassName("teaser")
+
+ for (let i = 0; i < data.length; ++i) {
+ let innerText = data[i].innerText
+ for (let j = 0; j < keywords.length; ++j) {
+ if (innerText.includes(keywords[j]) && data[i].offsetParent !== null) {
+ data[i].offsetParent.style.display = "none"
+ }
+ }
+ }
+})
diff --git a/4chan.org/4c-gallery.js b/4chan.org/4c-gallery.js
new file mode 100644
index 0000000..9ed1da9
--- /dev/null
+++ b/4chan.org/4c-gallery.js
@@ -0,0 +1,252 @@
+// ==UserScript==
+// @name 4c-gallery
+// @description Draggable image viewer
+// @author ae
+// @namespace Violentmonkey Scripts
+// @match *://boards.4chan*.org/*/thread/*
+// @exclude *://boards.4chan*.org/*/catalog
+// @version 1.3.2
+// ==/UserScript==
+
+/*
+Default shortcuts:
+ "-" decrease window size
+ "+" increase window size
+ "j" previous image
+ "k" next image
+ "i" jump to the source (i.e. post's hash)
+ "l" open the image to a new tab
+*/
+
+const keys = ["-", "+", "j", "k", "i", "l"]
+const excludeWebm = true // not tested with webms enabled
+
+const dragElement = (elem) => {
+ const handler = (e) => {
+ e = e || window.event
+ e.preventDefault()
+ pos3 = e.clientX
+ pos4 = e.clientY
+ document.onmouseup = closeDragger
+ document.onmousemove = enableDragger
+ }
+
+ const enableDragger = (e) => {
+ e = e || window.event
+ e.preventDefault()
+
+ pos1 = pos3 - e.clientX
+ pos2 = pos4 - e.clientY
+ pos3 = e.clientX
+ pos4 = e.clientY
+
+ elem.style.top = elem.offsetTop - pos2 + "px"
+ elem.style.left = elem.offsetLeft - pos1 + "px"
+ }
+
+ const closeDragger = () => {
+ document.onmouseup = null
+ document.onmousemove = null
+ }
+
+ let pos1, pos2, pos3, pos4
+
+ if (document.getElementsByClassName("drDrag").length > 0) {
+ document.getElementsByClassName("drDrag")[0].onmousedown = handler
+ } else {
+ elem.onmousedown = handler
+ }
+}
+
+const prevImg = () => {
+ if (i === 0) {
+ i = imgs.length - 1
+ } else {
+ i--
+ }
+
+ imgElem.src = imgs[i].src
+}
+
+const nextImg = () => {
+ if (i === imgs.length - 1) {
+ i = 0
+ } else {
+ i++
+ }
+
+ imgElem.src = imgs[i].src
+}
+
+const sizeUp = () => {
+ const newW = baseElem.clientWidth + 200
+ const newH = Math.round(newW * ratioMultiplier)
+
+ if (newW > window.innerWidth) {
+ return
+ }
+
+ baseElem.style.width = newW + "px"
+ baseElem.style.height = newH + "px"
+}
+
+const sizeDown = () => {
+ const newW = baseElem.clientWidth - 200
+ const newH = Math.round(newW * ratioMultiplier)
+
+ if (newW < 265 || newH < 240) {
+ return
+ }
+
+ baseElem.style.width = newW + "px"
+ baseElem.style.height = newH + "px"
+}
+
+const moveToHash = () => {
+ const hash = sources[i][1]
+ const url = window.location.href.split("#")[0]
+
+ window.location.href = url + hash
+}
+
+const openToNew = () => {
+ const url = sources[i][0]
+ window.open(url, "_blank")
+}
+
+const preloadImgs = async () => {
+ for (let s of sources) {
+ let img = new Image()
+ img.src = s[0]
+ await img.decode()
+ imgs.push(img)
+ }
+}
+
+const keyUpEvent = async (e) => {
+ if (["input", "textarea"].includes(e.target.tagName.toLowerCase())) {
+ return
+ }
+
+ switch (e.key) {
+ case keys[0]:
+ sizeDown()
+ break
+ case keys[1]:
+ sizeUp()
+ break
+ case keys[2]:
+ prevImg()
+ break
+ case keys[3]:
+ nextImg()
+ break
+ case keys[4]:
+ moveToHash()
+ break
+ case keys[5]:
+ openToNew()
+ break
+ }
+}
+
+const createElements = () => {
+ const limitElem = document.getElementsByClassName("boardBanner")[0]
+ const newNode = document.createElement("div")
+ newNode.innerHTML = `
`
+
+ const initW = "265px"
+ const initH = Math.round(265 * ratioMultiplier) + "px"
+
+ const stylesheet = document.createElement("style")
+ stylesheet.innerText = `#drGallery {
+ position: absolute;
+ z-index: 9;
+ font-weight: bold;
+ text-align: center;
+ border: 1px solid black;
+ width: ${initW};
+ height: ${initH};
+ min-width: ${initW};
+ min-height: ${initH};
+ display: none;
+ flex-direction: column;
+}
+
+#drHeader {
+ min-height: max-content;
+ padding: 5px;
+}
+
+#drContainer {
+ width: inherit;
+ height: 100%;
+ position: relative;
+}
+
+#drContainer img {
+ max-width: 100%;
+ max-height: 98%;
+ width: auto;
+ height: auto;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ margin: auto;
+}`
+
+ document.head.appendChild(stylesheet)
+ document.body.insertBefore(newNode, limitElem)
+ document.getElementsByClassName("navLinks desktop")[0].innerHTML +=
+ " [Gallery]"
+}
+
+const collectSources = () => {
+ let sources = []
+
+ const fileDivs = document.getElementsByClassName("fileThumb")
+ const hashPrefix = document
+ .getElementsByClassName("postNum")[0]
+ .children[0].hash.slice(0, 3)
+
+ for (let e of fileDivs) {
+ const s = e.href.split(".")
+ const filetype = s[s.length - 1]
+
+ if (excludeWebm && filetype === "webm") {
+ continue
+ }
+
+ // div's id to post's hash (prefix x): fT12345678 => #px12345678
+ sources.push([e.href, hashPrefix + e.parentElement.id.slice(2)])
+ }
+
+ return sources
+}
+
+window.toggleGalleryVisibility = () => {
+ if (baseElem.style.display === "flex") {
+ baseElem.style.display = "none"
+ document.removeEventListener("keyup", keyUpEvent, false)
+ } else {
+ baseElem.style.display = "flex"
+ document.addEventListener("keyup", keyUpEvent, false)
+ }
+}
+
+const ratioMultiplier = window.innerHeight / window.innerWidth
+createElements()
+
+let i = 0
+let imgs = []
+const sources = collectSources()
+preloadImgs().then(() => console.log("4c-gallery: All images loaded"))
+
+const baseElem = document.getElementById("drGallery")
+const imgElem = document.getElementById("drImg")
+dragElement(baseElem)
diff --git a/visual/4c-image-expander.js b/4chan.org/4c-image-expander.js
similarity index 50%
rename from visual/4c-image-expander.js
rename to 4chan.org/4c-image-expander.js
index b1b96b1..92a75e8 100644
--- a/visual/4c-image-expander.js
+++ b/4chan.org/4c-image-expander.js
@@ -1,26 +1,27 @@
-// ==UserScript==
-// @name 4c-image-expander
-// @description General media expander
-// @namespace Violentmonkey Scripts
-// @match *://boards.4chan*.org/*/thread/*
-// @exclude *://boards.4chan*.org/*/catalog
-// @version 1.0
-// ==/UserScript==
-
-window.toggleImgs = () => {
- const data = document.getElementsByClassName("fileThumb")
-
- for (let i = 0; i < data.length; ++i) {
- let img_data = data[i].getElementsByTagName("img")
- if (img_data[0].className === "fileDeletedRes retina") {
- continue
- } else if (img_data.length === 1) {
- ImageExpansion.expand(img_data[0])
- } else {
- ImageExpansion.contract(img_data[1])
- }
- }
-}
-
-const parentElem = document.getElementsByClassName("navLinks desktop")[0]
-parentElem.innerHTML += " [Toggle]"
+// ==UserScript==
+// @name 4c-image-expander
+// @description General media expander
+// @author ae
+// @namespace Violentmonkey Scripts
+// @match *://boards.4chan*.org/*/thread/*
+// @exclude *://boards.4chan*.org/*/catalog
+// @version 1.0
+// ==/UserScript==
+
+window.toggleImgs = () => {
+ const data = document.getElementsByClassName("fileThumb")
+
+ for (let i = 0; i < data.length; ++i) {
+ let img_data = data[i].getElementsByTagName("img")
+ if (img_data[0].className === "fileDeletedRes retina") {
+ continue
+ } else if (img_data.length === 1) {
+ ImageExpansion.expand(img_data[0])
+ } else {
+ ImageExpansion.contract(img_data[1])
+ }
+ }
+}
+
+const parentElem = document.getElementsByClassName("navLinks desktop")[0]
+parentElem.innerHTML += " [Toggle]"
diff --git a/README.md b/README.md
deleted file mode 100644
index 0b15038..0000000
--- a/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-## Collection of small userscripts
-
-Tested with [Violentmonkey](https://violentmonkey.github.io/). Available on [Greasyfork](https://greasyfork.org/en/users/1033565-17ms).
-
-- [4c-autohide.js](visual/4c-autohide.js)
-- [4c-gallery.js](visual/4c-gallery.js)
-- [4c-image-expander.js](visual/4c-image-expander.js)
-- [y-image-expander.js](visual/y-image-expander.js)
-- [y-media-downloader.js](download/y-media-downloader.js)
diff --git a/download/y-media-downloader.js b/download/y-media-downloader.js
deleted file mode 100644
index 719866c..0000000
--- a/download/y-media-downloader.js
+++ /dev/null
@@ -1,43 +0,0 @@
-// ==UserScript==
-// @name y-media-downloader
-// @description General media downloader
-// @author 17ms
-// @license MIT License
-// @namespace Violentmonkey Scripts
-// @match *://ylilauta.org/*
-// @version 1.0
-// ==/UserScript==
-
-function download(url) {
- fetch(url, {
- mode: "no-cors",
- })
- .then((response) => response.blob())
- .then((blob) => {
- let blob_url = window.URL.createObjectURL(blob)
- let a = document.createElement("a")
- a.download = url.split("/")[5]
- a.href = blob_url
- document.body.appendChild(a)
- a.click()
- a.remove()
- })
-}
-
-function init() {
- const links = Array.from(document.getElementsByClassName("jpg")).concat(
- Array.from(document.getElementsByClassName("png"))
- )
-
- for (let i = 0; i < links.length; ++i) {
- let url = links[i].href
- download(url)
- }
-}
-
-const activate_link = document.createElement("button")
-const parent_element = document.getElementById("navbar")
-activate_link.innerText = "⮶"
-activate_link.style.fontSize = "30px"
-activate_link.onclick = () => init()
-parent_element.append(activate_link)
diff --git a/visual/4c-autohide.js b/visual/4c-autohide.js
deleted file mode 100644
index 9bbc4d8..0000000
--- a/visual/4c-autohide.js
+++ /dev/null
@@ -1,23 +0,0 @@
-// ==UserScript==
-// @name 4c-autohide
-// @description Keyword based thread hider
-// @author 17ms
-// @license MIT License
-// @namespace Violentmonkey Scripts
-// @match *://boards.4chan*.org/*/catalog
-// @version 1.0
-// ==/UserScript==
-
-window.addEventListener("load", () => {
- const keywords = [] // e.g. ["/sdg/", "luke smith"]
- const data = document.getElementsByClassName("teaser")
-
- for (let i = 0; i < data.length; ++i) {
- let innerText = data[i].innerText
- for (let j = 0; j < keywords.length; ++j) {
- if (innerText.includes(keywords[j]) && data[i].offsetParent !== null) {
- data[i].offsetParent.style.display = "none"
- }
- }
- }
-})
diff --git a/visual/4c-gallery.js b/visual/4c-gallery.js
deleted file mode 100644
index 7e1ea85..0000000
--- a/visual/4c-gallery.js
+++ /dev/null
@@ -1,253 +0,0 @@
-// ==UserScript==
-// @name 4c-gallery
-// @description Draggable image viewer
-// @author 17ms
-// @license MIT License
-// @namespace Violentmonkey Scripts
-// @match *://boards.4chan*.org/*/thread/*
-// @exclude *://boards.4chan*.org/*/catalog
-// @version 1.3.2
-// ==/UserScript==
-
-/*
-Default shortcuts:
- "-" decrease window size
- "+" increase window size
- "j" previous image
- "k" next image
- "i" jump to the source (i.e. post's hash)
- "l" open the image to a new tab
-*/
-
-const keys = ["-", "+", "j", "k", "i", "l"]
-const excludeWebm = true // not tested with webms enabled
-
-const dragElement = (elem) => {
- const handler = (e) => {
- e = e || window.event
- e.preventDefault()
- pos3 = e.clientX
- pos4 = e.clientY
- document.onmouseup = closeDragger
- document.onmousemove = enableDragger
- }
-
- const enableDragger = (e) => {
- e = e || window.event
- e.preventDefault()
-
- pos1 = pos3 - e.clientX
- pos2 = pos4 - e.clientY
- pos3 = e.clientX
- pos4 = e.clientY
-
- elem.style.top = elem.offsetTop - pos2 + "px"
- elem.style.left = elem.offsetLeft - pos1 + "px"
- }
-
- const closeDragger = () => {
- document.onmouseup = null
- document.onmousemove = null
- }
-
- let pos1, pos2, pos3, pos4
-
- if (document.getElementsByClassName("drDrag").length > 0) {
- document.getElementsByClassName("drDrag")[0].onmousedown = handler
- } else {
- elem.onmousedown = handler
- }
-}
-
-const prevImg = () => {
- if (i === 0) {
- i = imgs.length - 1
- } else {
- i--
- }
-
- imgElem.src = imgs[i].src
-}
-
-const nextImg = () => {
- if (i === imgs.length - 1) {
- i = 0
- } else {
- i++
- }
-
- imgElem.src = imgs[i].src
-}
-
-const sizeUp = () => {
- const newW = baseElem.clientWidth + 200
- const newH = Math.round(newW * ratioMultiplier)
-
- if (newW > window.innerWidth) {
- return
- }
-
- baseElem.style.width = newW + "px"
- baseElem.style.height = newH + "px"
-}
-
-const sizeDown = () => {
- const newW = baseElem.clientWidth - 200
- const newH = Math.round(newW * ratioMultiplier)
-
- if (newW < 265 || newH < 240) {
- return
- }
-
- baseElem.style.width = newW + "px"
- baseElem.style.height = newH + "px"
-}
-
-const moveToHash = () => {
- const hash = sources[i][1]
- const url = window.location.href.split("#")[0]
-
- window.location.href = url + hash
-}
-
-const openToNew = () => {
- const url = sources[i][0]
- window.open(url, "_blank")
-}
-
-const preloadImgs = async () => {
- for (let s of sources) {
- let img = new Image()
- img.src = s[0]
- await img.decode()
- imgs.push(img)
- }
-}
-
-const keyUpEvent = async (e) => {
- if (["input", "textarea"].includes(e.target.tagName.toLowerCase())) {
- return
- }
-
- switch (e.key) {
- case keys[0]:
- sizeDown()
- break
- case keys[1]:
- sizeUp()
- break
- case keys[2]:
- prevImg()
- break
- case keys[3]:
- nextImg()
- break
- case keys[4]:
- moveToHash()
- break
- case keys[5]:
- openToNew()
- break
- }
-}
-
-const createElements = () => {
- const limitElem = document.getElementsByClassName("boardBanner")[0]
- const newNode = document.createElement("div")
- newNode.innerHTML = ``
-
- const initW = "265px"
- const initH = Math.round(265 * ratioMultiplier) + "px"
-
- const stylesheet = document.createElement("style")
- stylesheet.innerText = `#drGallery {
- position: absolute;
- z-index: 9;
- font-weight: bold;
- text-align: center;
- border: 1px solid black;
- width: ${initW};
- height: ${initH};
- min-width: ${initW};
- min-height: ${initH};
- display: none;
- flex-direction: column;
-}
-
-#drHeader {
- min-height: max-content;
- padding: 5px;
-}
-
-#drContainer {
- width: inherit;
- height: 100%;
- position: relative;
-}
-
-#drContainer img {
- max-width: 100%;
- max-height: 98%;
- width: auto;
- height: auto;
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
- margin: auto;
-}`
-
- document.head.appendChild(stylesheet)
- document.body.insertBefore(newNode, limitElem)
- document.getElementsByClassName("navLinks desktop")[0].innerHTML +=
- " [Gallery]"
-}
-
-const collectSources = () => {
- let sources = []
-
- const fileDivs = document.getElementsByClassName("fileThumb")
- const hashPrefix = document
- .getElementsByClassName("postNum")[0]
- .children[0].hash.slice(0, 3)
-
- for (let e of fileDivs) {
- const s = e.href.split(".")
- const filetype = s[s.length - 1]
-
- if (excludeWebm && filetype === "webm") {
- continue
- }
-
- // div's id to post's hash (prefix x): fT12345678 => #px12345678
- sources.push([e.href, hashPrefix + e.parentElement.id.slice(2)])
- }
-
- return sources
-}
-
-window.toggleGalleryVisibility = () => {
- if (baseElem.style.display === "flex") {
- baseElem.style.display = "none"
- document.removeEventListener("keyup", keyUpEvent, false)
- } else {
- baseElem.style.display = "flex"
- document.addEventListener("keyup", keyUpEvent, false)
- }
-}
-
-const ratioMultiplier = window.innerHeight / window.innerWidth
-createElements()
-
-let i = 0
-let imgs = []
-const sources = collectSources()
-preloadImgs().then(() => console.log("4c-gallery: All images loaded"))
-
-const baseElem = document.getElementById("drGallery")
-const imgElem = document.getElementById("drImg")
-dragElement(baseElem)
diff --git a/visual/y-image-expander.js b/visual/y-image-expander.js
deleted file mode 100644
index 744f9c8..0000000
--- a/visual/y-image-expander.js
+++ /dev/null
@@ -1,29 +0,0 @@
-// ==UserScript==
-// @name y-image-expander
-// @description General media expander
-// @author 17ms
-// @license MIT License
-// @namespace Violentmonkey Scripts
-// @match *://ylilauta.org/*
-// @version 1.0
-// ==/UserScript==
-
-const toggleImages = () => {
- const mediaJpg = document.querySelectorAll("a.jpg")
- const mediaPng = document.querySelectorAll("a.png")
-
- for (let i = 0; i < mediaJpg.length; ++i) {
- mediaJpg[i].click()
- }
-
- for (let i = 0; i < mediaPng.length; ++i) {
- mediaPng[i].click()
- }
-}
-
-const activateLink = document.createElement("button")
-const parentElem = document.getElementById("navbar")
-activateLink.innerText = "Toggle"
-activateLink.style.fontSize = "9px"
-activateLink.onclick = () => toggleImages()
-parentElem.append(activateLink)