Last active
December 23, 2020 18:36
-
-
Save a-gu/8313d8523f5e8a08e80b54beb1d7b241 to your computer and use it in GitHub Desktop.
Rewrites the WebToon viewer to still be functional with fewer resources
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name WebToon Light | |
// @version 1.0 | |
// @description Rewrites the WebToon viewer to still be functional with fewer resources | |
// @author Andrew Gu | |
// @match https://www.webtoons.com/*viewer | |
// @match https://www.webtoons.com/*viewer?* | |
// @updateURL https://gist.github.com/a-gu/8313d8523f5e8a08e80b54beb1d7b241/raw/97ff557a0267dfc3929e63cf41873c161008239f/webtoon_light.user.js | |
// @grant none | |
// @run-at document-end | |
// ==/UserScript== | |
/* | |
Designed to be used in tandem with filtering rules like (uBlock Origin): | |
webtoons.com * 1p-script block | |
webtoons.com * 3p-script block | |
webtoons.com * image allow | |
webtoons.com * inline-script allow | |
*/ | |
(function() { | |
'use strict'; | |
const USER_STYLE = ` | |
/* Global */ | |
body { | |
margin: 0; | |
height: 100vh; | |
overflow-y: hidden; | |
display: grid; | |
grid-template-columns: 20em auto; | |
grid-template-areas: "sidebar content" "sidebar content"; | |
background-color: #000000; | |
color: #ffffff | |
} | |
a { | |
color: #88ff88; | |
text-decoration: none; | |
padding: 0.2em; | |
} | |
a:not(.subj), | |
.episode_cont li[data-episode-no] { | |
transform: scale(1.0); | |
transition: transform 0.2s ease | |
} | |
:not(.episode_cont li[data-episode-no]) > a:not(.subj):hover, | |
.episode_cont li[data-episode-no]:hover { | |
transform: scale(1.05) | |
} | |
/* Sidebar */ | |
.sidebar { | |
display: flex; | |
flex-flow: column nowrap; | |
height: 100%; | |
overflow: hidden | |
} | |
/* Info */ | |
.subj_info { | |
padding: 0.5em | |
} | |
.subj_episode, .subj_info>a { | |
text-overflow: ellipsis; | |
overflow: hidden; | |
display: block; | |
margin: 0 | |
} | |
/* Pagination */ | |
.paginate { | |
padding: 0.5em; | |
border-bottom: 0.25em dashed #222222; | |
display: flex; | |
flex-flow: row nowrap; | |
justify-content: space-between; | |
margin-bottom: 0.25em; | |
align-items: center | |
} | |
/* Episodes List */ | |
.episode_cont { | |
flex-shrink: 1; | |
flex-grow: 1; | |
overflow-y: auto; | |
word-break: break-word; | |
overflow-x: hidden | |
} | |
.episode_cont>ul { | |
list-style: none; | |
margin: 0; | |
padding: 0; | |
display: flex; | |
flex-flow: column-reverse nowrap | |
} | |
.episode_cont li[data-episode-no]>a { | |
display: flex; | |
flex-flow: row nowrap; | |
align-items: center | |
} | |
.episode_cont li[data-episode-no]:nth-child(2n) { | |
background-color: #ffffff22 | |
} | |
.episode_cont li[data-episode-no] .subj { | |
padding: 0.5em | |
} | |
.episode_cont li[data-episode-no].current { | |
z-index: 9; | |
background-color: #88ff8833 | |
} | |
.episode_cont li[data-episode-no].current a { | |
color: #ffffff | |
} | |
/* Images */ | |
#_imageList { | |
line-height: 0; | |
overflow-y: auto; | |
} | |
` | |
// Extract elements and create custon layout | |
let info = document.querySelector('#toolbar > .info > .subj_info'), | |
pages = document.querySelector('#toolbar > .paginate'), | |
episodes = document.querySelector('#toolbar > #topEpisodeList .episode_cont'), | |
images = document.querySelector('#_imageList') | |
let content = document.createDocumentFragment(), | |
sidebar = document.createElement('div'), | |
style = document.createElement('style') | |
style.setAttribute('type', 'text/css') | |
style.innerHTML = USER_STYLE | |
sidebar.classList.add('sidebar') | |
sidebar.appendChild(info) | |
sidebar.appendChild(pages) | |
pages.querySelector('.pg_prev em').innerText = '< Prev' | |
pages.querySelector('.pg_next em').innerText = 'Next >' | |
sidebar.appendChild(episodes) | |
content.appendChild(sidebar) | |
content.appendChild(images) | |
// Rewrite all images | |
Array.from(content.querySelectorAll('img[src*="transparency.png"][data-url]')).forEach(img => { | |
img.setAttribute('loading', 'lazy'); | |
img.setAttribute('src', img.getAttribute('data-url')); | |
['ondragstart', 'onselectstart', 'oncontextmenu', 'data-url', 'class'].forEach(attr => img.removeAttribute(attr)) | |
}) | |
// Clear page and write new content | |
document.open() | |
document.write('<!DOCTYPE html><html><head></head><body></body></html>') | |
document.close() | |
document.head.appendChild(style) | |
document.body.appendChild(content) | |
// Scroll to current episode | |
let episode = (new URL(window.location)).searchParams.get('episode_no'), | |
episode_li = document.querySelector(`.episode_cont li[data-episode-no="${episode}"]`) | |
episode_li.classList.add('current'); | |
(episode_li.nextElementSibling || episode_li).scrollIntoView() | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment