Last active
August 10, 2024 16:31
-
-
Save teidesu/e1ad8ebcb0a90290e7fd4fcc02403af3 to your computer and use it in GitHub Desktop.
all my homies hate svelte
This file contains 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 no svelte | |
// @description all my homies hate svelte | |
// @namespace teidesu | |
// @match *://*/* | |
// @grant window.close | |
// @grant GM_addElement | |
// @grant GM_getValue | |
// @grant GM_setValue | |
// @grant GM.getValue | |
// @grant GM.setValue | |
// @version 1.1 | |
// @author teidesu | |
// @downloadURL https://gist.githubusercontent.com/teidesu/e1ad8ebcb0a90290e7fd4fcc02403af3/raw/no-svelte.user.js | |
// ==/UserScript== | |
const exportFunction = this.exportFunction ?? (a => a) | |
let getValue, setValue; | |
{ | |
let isGM = false | |
try { | |
isGM = Boolean(GM) | |
} catch {} | |
if (isGM) { | |
getValue = async function getValue(key) { | |
return await GM.getValue(key) | |
} | |
setValue = async function setValue(key, value) { | |
return await GM.setValue(key, value) | |
} | |
} else { | |
getValue = async function getValue(key) { | |
return GM_getValue(key) | |
} | |
setValue = async function setValue(key, value) { | |
return GM_setValue(key, value) | |
} | |
} | |
} | |
// this.GM_addElement ?? | |
const addElement = window.GM_addElement || function addElement(parent, name, props) { | |
if (typeof parent === 'string') { | |
[name, props] = [parent, name] | |
parent = document.body | |
} | |
let element = document.createElement(name) | |
if (props) | |
Object.assign(element, props) | |
parent.appendChild(element) | |
return element | |
} | |
const POPUP_CSS = ` | |
.popup { | |
position: absolute; | |
left: 0; | |
top: 0; | |
width: 100%; | |
height: 100%; | |
z-index: 999999999999; | |
background: #fefefe; | |
font-family: sans-serif; | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
justify-content: center; | |
color: #222; | |
color-scheme: light; | |
} | |
.title { | |
font-size: 24px; | |
font-weight: 600; | |
margin-bottom: 16px; | |
} | |
.subtitle { | |
font-size: 18px; | |
margin-bottom: 8px; | |
} | |
.question { | |
font-size: 14px; | |
margin-bottom: 24px; | |
} | |
.buttons { | |
display: flex; | |
gap: 12px; | |
} | |
.buttons button { | |
border: none; | |
border-radius: 8px; | |
padding: 8px 16px; | |
cursor: pointer; | |
margin-bottom: 10px; | |
color: #222; | |
} | |
#button-yes { | |
background: #fecccc; | |
} | |
#button-yes:hover { | |
background: #febbbb; | |
} | |
#button-yes:active { | |
background: #feaaaa; | |
} | |
#button-no { | |
background: #efefef; | |
} | |
#button-no:hover { | |
background: #dedede; | |
} | |
#button-no:active { | |
background: #cdcdcd; | |
} | |
.checkbox { | |
font-size: 12px; | |
display: flex; | |
align-items: center; | |
gap: 4px; | |
color: #666; | |
} | |
@media (prefers-color-scheme: dark) { | |
.popup { | |
background: #202020; | |
color: #fefefe; | |
color-scheme: dark; | |
} | |
#button-yes { | |
background: #aa3333; | |
} | |
#button-yes:hover { | |
background: #bb3333; | |
} | |
#button-yes:active { | |
background: #cc3333; | |
} | |
#button-no { | |
background: #404040; | |
} | |
#button-no:hover { | |
background: #505050; | |
} | |
#button-no:active { | |
background: #606060; | |
} | |
} | |
`.trim() | |
const POPUP_HTML = ({ svelteVersion }) => ` | |
<div class="popup"> | |
<div class="title">Hol' up!</div> | |
<div class="subtitle">💩 This page uses Svelte (v${svelteVersion})</div> | |
<div class="question">Do you <i>really</i> want to proceed?</div> | |
<div class="buttons"> | |
<button id="button-yes">Yes</button> | |
<button id="button-no">No</button> | |
</div> | |
<div class="checkbox"> | |
<input type="checkbox" id="remember"> | |
<label for="remember">Remember my choice</label> | |
</div> | |
</div> | |
`.trim() | |
const STORAGE_KEY = `no-svelte:${location.hostname}` | |
async function displayPopup(svelteVersion) { | |
const stored = await getValue(STORAGE_KEY) | |
if (stored === 'yes') return | |
if (stored === 'no') return window.close() | |
const popupWrap = addElement('no-svelte-host') | |
const shadow = popupWrap.attachShadow({ mode: 'open' }) | |
const popup = addElement(shadow, 'div') | |
popup.innerHTML = POPUP_HTML({ svelteVersion }) | |
addElement(popup, 'style', { textContent: POPUP_CSS }) | |
const oldBodyOverflow = document.body.style.overflow | |
document.body.style.overflow = 'hidden' | |
const remember = () => popup.querySelector('#remember').checked | |
popup.querySelector('#button-yes').addEventListener('click', async () => { | |
if (remember()) | |
await setValue(STORAGE_KEY, 'yes') | |
popupWrap.remove(); | |
document.body.style.overflow = oldBodyOverflow | |
}) | |
popup.querySelector('#button-no').addEventListener('click', async () => { | |
if (remember()) | |
await setValue(STORAGE_KEY, 'no') | |
window.close() | |
}) | |
} | |
function detectSvelte(unsafeSvelte) { | |
let firstValue = unsafeSvelte.v.values().next().value | |
if (firstValue !== undefined) { | |
displayPopup(firstValue) | |
} else { | |
unsafeSvelte.v.add = exportFunction(function(v) { | |
displayPopup(v) | |
if (this.wrappedJSObject) | |
delete this.wrappedJSObject.add | |
else | |
delete this.add | |
Reflect.apply(unsafeWindow.Set.prototype.add, this, [v]) | |
}, unsafeSvelte) | |
} | |
} | |
if (unsafeWindow.__svelte) { | |
detectSvelte(unsafeWindow.__svelte) | |
} else { | |
let svelte | |
const exportedGet = exportFunction(() => { | |
return svelte | |
}, unsafeWindow) | |
const exportedSet = exportFunction((v) => { | |
if (v.wrappedJSObject) | |
v = v.wrappedJSObject | |
detectSvelte(v) | |
svelte = v | |
return true | |
}, unsafeWindow) | |
Object.defineProperty(unsafeWindow, '__svelte', { | |
get: exportedGet, | |
set: exportedSet | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment