- // ==UserScript==
- // @name Lemmy Universal Link Switcher
- // @namespace http://azzurite.tv/
- // @license GPLv3
- // @version 1.2.4
- // @description Ensures that all URLs to Lemmy instances always point to your main/home instance.
- // @homepageURL https://gitlab.com/azzurite/lemmy-universal-link-switcher
- // @supportURL https://gitlab.com/azzurite/lemmy-universal-link-switcher/-/issues
- // @author Azzurite
- // @match *://*/*
- // @icon https://gitlab.com/azzurite/lemmy-universal-link-switcher/-/raw/main/resources/favicon.png?inline=true
- // @grant GM.setValue
- // @grant GM.getValue
- // @grant GM.xmlHttpRequest
- // @connect *
- // @require https://unpkg.com/@popperjs/core@2
- // @require https://unpkg.com/tippy.js@6
- // ==/UserScript==
-
- (() => {
- // src/debug.js
- var DEBUG = false;
- function debug() {
- if (DEBUG)
- console.debug(`Rewriter | `, ...arguments);
- }
- function trace() {
- if (DEBUG === `trace`)
- console.debug(`Rewriter Trace | `, ...arguments);
- }
-
- // src/instances.js
- function isLemmyInstance(url) {
- return isInstance(INSTANCES_LEMMY, url);
- }
- function isKbinInstance(url) {
- return isInstance(INSTANCES_KBIN, url);
- }
- function isInstance(instances, url) {
- if (url.origin) {
- return instances.has(url.origin);
- } else {
- return false;
- }
- }
- trace(`Define instances sets start`);
- var INSTANCES_LEMMY = /* @__PURE__ */ new Set([
- "http://lemmy.brdsnest.net",
- "https://0v0.social",
- "https://0xdd.org.ru",
- "https://1337lemmy.com",
- "https://158436977.xyz",
- "https://2dl.eu",
- "https://acqrs.co.uk",
- "https://actuallyruben.nl",
- "https://ag.batlord.org",
- "https://aggregation.cafe",
- "https://agora.nop.chat",
- "https://aiparadise.moe",
- "https://alfredoautomation.com",
- "https://algebro.xyz",
- "https://americas.cloud",
- "https://androiddev.network",
- "https://ani.social",
- "https://animoe.xyz",
- "https://apollo.town",
- "https://areality.social",
- "https://arpa.dev",
- "https://ascy.mooo.com",
- "https://atosoul.asuscomm.com",
- "https://aulem.org",
- "https://aussie.zone",
- "https://baomi.tv",
- "https://baraza.africa",
- "https://bbg.lol",
- "https://bbs.9tail.net",
- "https://bbs.darkwitch.net",
- "https://beehaw.org",
- "https://beer.andma.la",
- "https://beevibes.net",
- "https://bethe.kingofdog.de",
- "https://biglemmowski.win",
- "https://bin.pztrn.online",
- "https://bluuit.org",
- "https://board.minimally.online",
- "https://bookwormstory.social",
- "https://borg.chat",
- "https://botnet.club",
- "https://bubblesthebunny.com",
- "https://bulletintree.com",
- "https://burrp.xyz",
- "https://butts.international",
- "https://c.calciumlabs.com",
- "https://caint.org",
- "https://campfyre.nickwebster.dev",
- "https://cavy.rocks",
- "https://cdda.social",
- "https://centennialstate.social",
- "https://chat.maiion.com",
- "https://cigar.cx",
- "https://civilloquy.com",
- "https://clatter.eu",
- "https://cnvrs.net",
- "https://cocte.au",
- "https://code4lib.net",
- "https://coeus.sbs",
- "https://communick.news",
- "https://communities.azkware.net",
- "https://community.adiquaints.moe",
- "https://community.destinovate.com",
- "https://community.nicfab.it",
- "https://compuverse.uk",
- "https://crystals.rest",
- "https://culture0.cc",
- "https://cybercrime.zip",
- "https://dandroid.app",
- "https://darmok.xyz",
- "https://databend.run",
- "https://demmy.co.uk",
- "https://demotheque.com",
- "https://dendarii.alaeron.com",
- "https://derp.foo",
- "https://derpzilla.net",
- "https://dgngrnder.com",
- "https://diggit.xyz",
- "https://digipres.cafe",
- "https://digitalgoblin.uk",
- "https://discuss.as200950.com",
- "https://discuss.divergentparenting.space",
- "https://discuss.dizl.de",
- "https://discuss.icewind.me",
- "https://discuss.jacen.moe",
- "https://discuss.ntfy.sh",
- "https://discuss.online",
- "https://discuss.tchncs.de",
- "https://distress.digital",
- "https://dmv.social",
- "https://donky.social",
- "https://dork.farm",
- "https://dormi.zone",
- "https://drachennetz.com",
- "https://drak.gg",
- "https://drlemmy.net",
- "https://ds9.lemmy.ml",
- "https://dsilo061298.ddns.net",
- "https://dubvee.org",
- "https://ducks.dev",
- "https://einweckglas.com",
- "https://endlesstalk.org",
- "https://endofti.me",
- "https://enterprise.lemmy.ml",
- "https://eslemmy.es",
- "https://eventfrontier.com",
- "https://eviltoast.org",
- "https://exploding-heads.com",
- "https://ezlemmy.io",
- "https://f.jbradaric.me",
- "https://f.soopy.moe",
- "https://fadoverso.pt",
- "https://fanaticus.social",
- "https://fanexus.com",
- "https://fed.creve.com",
- "https://fed.rosssi.co.uk",
- "https://feddi.no",
- "https://feddit.afop.tech",
- "https://feddit.at",
- "https://feddit.ch",
- "https://feddit.cl",
- "https://feddit.de",
- "https://feddit.dk",
- "https://feddit.dnico.io",
- "https://feddit.eu",
- "https://feddit.fun",
- "https://feddit.it",
- "https://feddit.jp",
- "https://feddit.nl",
- "https://feddit.nu",
- "https://feddit.nz",
- "https://feddit.pl",
- "https://feddit.ro",
- "https://feddit.rocks",
- "https://feddit.site",
- "https://feddit.strike23.de",
- "https://feddit.uk",
- "https://feddit.win",
- "https://federated.community",
- "https://fedibb.ml",
- "https://fedii.me",
- "https://fedit.io",
- "https://feditown.com",
- "https://fediverse.ro",
- "https://fedjlailu.fr",
- "https://feed.newt.wtf",
- "https://feed.sokolik.info",
- "https://feedly.j-cloud.uk",
- "https://femboys.bar",
- "https://fenbushi.site",
- "https://fernchat.esotericmonkey.com",
- "https://fjdk.uk",
- "https://fl0w.cc",
- "https://forkk.me",
- "https://foro.markoop.org",
- "https://foros.fediverso.gal",
- "https://forum.basedcount.com",
- "https://forum.bruvland.com",
- "https://forum.liberatedsystems.co.uk",
- "https://forum.stellarcastle.net",
- "https://fost.hu",
- "https://frig.social",
- "https://gadgetro.id",
- "https://gathering.pikafan.de",
- "https://geddit.social",
- "https://gekinzuku.com",
- "https://gertie.uk",
- "https://gioia.news",
- "https://glasstower.nl",
- "https://gmestock.com",
- "https://goddess.name",
- "https://gonelemmy.xyz",
- "https://granitestate.social",
- "https://greg.city",
- "https://grinnit.grin.hu",
- "https://group.lt",
- "https://grumpf.horcrux.dev",
- "https://grumpy.schuppentier.club",
- "https://hakbox.social",
- "https://halubilo.social",
- "https://hammerdown.0fucks.nl",
- "https://heckoverflow.net",
- "https://heylemmy.heybro.nz",
- "https://hive.atlanten.se",
- "https://hoodlem.me",
- "https://hoodratshit.org",
- "https://hyperfair.link",
- "https://iboughtthisdomainbecauseithoughtitscheap.uk",
- "https://iceorchid.net",
- "https://info.prou.be",
- "https://infosec.pub",
- "https://insane.dev",
- "https://invariant-marxism.red",
- "https://iusearchlinux.fyi",
- "https://jalim.xyz",
- "https://jamie.moe",
- "https://jasdemi.com",
- "https://jemmy.jeena.net",
- "https://jlai.lu",
- "https://ka.tet42.org",
- "https://keeb.lol",
- "https://kerala.party",
- "https://keylog.zip",
- "https://kleptonix.com",
- "https://klingon.nl",
- "https://krabb.org",
- "https://kulupu.duckdns.org",
- "https://kuu.kohana.fi",
- "https://kwarr.com",
- "https://kyu.de",
- "https://l.1in1.net",
- "https://l.60228.dev",
- "https://l.7rg1nt.moe",
- "https://l.antiope.link",
- "https://l.biendeo.com",
- "https://l.bxy.sh",
- "https://l.dustybeer.com",
- "https://l.jugregator.org",
- "https://l.lucitt.com",
- "https://l.mathers.fr",
- "https://l.mchome.net",
- "https://l.nulltext.org",
- "https://l.plabs.social",
- "https://l.rickebo.com",
- "https://l.roofo.cc",
- "https://l.tunahan.social",
- "https://l.twos.dev",
- "https://l.vidja.social",
- "https://labdegato.com",
- "https://laguna.chat",
- "https://latte.isnot.coffee",
- "https://le-me.xyz",
- "https://le.fduck.net",
- "https://le.mnau.xyz",
- "https://leaf.dance",
- "https://leby.dev",
- "https://leddit.danmark.party",
- "https://leddit.social",
- "https://lef.li",
- "https://lem.agoomem.xyz",
- "https://lem.ainyataovi.net",
- "https://lem.amd.im",
- "https://lem.clinicians-exchange.org",
- "https://lem.cochrun.xyz",
- "https://lem.cyb3rdelia.net",
- "https://lem.dru5k1.com",
- "https://lem.elbullazul.com",
- "https://lem.free.as",
- "https://lem.lyk.pw",
- "https://lem.monster",
- "https://lem.ph3j.com",
- "https://lem.serkozh.me",
- "https://lem.simple-gear.com",
- "https://lem.southcape.social",
- "https://lem.ur-mom.gay",
- "https://lem.zevs.me",
- "https://lemdit.com",
- "https://lemdro.id",
- "https://lemellem.dasonic.xyz",
- "https://lemitar.meta1203.com",
- "https://lemiverse.xyz",
- "https://lemm.ee",
- "https://lemmerz.org",
- "https://lemmie.be",
- "https://lemmings.basic-domain.com",
- "https://lemmings.world",
- "https://lemmit.online",
- "https://lemmit.xyz",
- "https://lemmonade.marbledfennec.net",
- "https://lemmony.click",
- "https://lemmus.org",
- "https://lemmy.01110100.xyz",
- "https://lemmy.0x3d.uk",
- "https://lemmy.1204.org",
- "https://lemmy.2kd.de",
- "https://lemmy.4d2.org",
- "https://lemmy.6px.eu",
- "https://lemmy.86thumbs.net",
- "https://lemmy.absolutesix.com",
- "https://lemmy.adambowl.es",
- "https://lemmy.aguiarvieira.pt",
- "https://lemmy.alexland.ca",
- "https://lemmy.amxl.com",
- "https://lemmy.amyjnobody.com",
- "https://lemmy.ananace.dev",
- "https://lemmy.animal-machine.com",
- "https://lemmy.anji.nl",
- "https://lemmy.anonion.social",
- "https://lemmy.antemeridiem.xyz",
- "https://lemmy.antisocial.ly",
- "https://lemmy.anymore.nl",
- "https://lemmy.appeine.com",
- "https://lemmy.arpatubes.net",
- "https://lemmy.arun.cloud",
- "https://lemmy.asc6.org",
- "https://lemmy.ashes.wtf",
- "https://lemmy.atay.dev",
- "https://lemmy.atheos.org",
- "https://lemmy.aucubin.de",
- "https://lemmy.austinite.online",
- "https://lemmy.austinvaness.com",
- "https://lemmy.austinwadeheller.com",
- "https://lemmy.avata.social",
- "https://lemmy.azamserver.com",
- "https://lemmy.bapp.run",
- "https://lemmy.barnacles.one",
- "https://lemmy.baswag.de",
- "https://lemmy.beckmeyer.us",
- "https://lemmy.beebl.es",
- "https://lemmy.beep.computer",
- "https://lemmy.belegost.net",
- "https://lemmy.benrasich.com",
- "https://lemmy.beru.co",
- "https://lemmy.beyondcombustion.net",
- "https://lemmy.bitgoblin.tech",
- "https://lemmy.bitlab21.com",
- "https://lemmy.biz",
- "https://lemmy.blackeco.com",
- "https://lemmy.blad.is",
- "https://lemmy.blahaj.zone",
- "https://lemmy.bleh.au",
- "https://lemmy.bloodmoon-network.de",
- "https://lemmy.blue",
- "https://lemmy.blugatch.tube",
- "https://lemmy.boats",
- "https://lemmy.borlax.com",
- "https://lemmy.bothhands.ca",
- "https://lemmy.brad.ee",
- "https://lemmy.bran.ink",
- "https://lemmy.brief.guru",
- "https://lemmy.bringdaruck.us",
- "https://lemmy.browntown.dev",
- "https://lemmy.brynstuff.co.uk",
- "https://lemmy.bulbousnub.com",
- "https://lemmy.buller.cc",
- "https://lemmy.bulwarkob.com",
- "https://lemmy.burger.rodeo",
- "https://lemmy.burningboard.net",
- "https://lemmy.buzz",
- "https://lemmy.ca",
- "https://lemmy.cablepick.net",
- "https://lemmy.cafe",
- "https://lemmy.caffeinated.social",
- "https://lemmy.calebmharper.com",
- "https://lemmy.calvss.com",
- "https://lemmy.cat",
- "https://lemmy.catgirl.biz",
- "https://lemmy.cevn.io",
- "https://lemmy.ch3n2k.com",
- "https://lemmy.chatterverse.social",
- "https://lemmy.chiisana.net",
- "https://lemmy.chromozone.dev",
- "https://lemmy.ciechom.eu",
- "https://lemmy.click",
- "https://lemmy.cloud.aboutcher.co.uk",
- "https://lemmy.cloudhub.social",
- "https://lemmy.cloudsecurityofficehours.com",
- "https://lemmy.clueware.org",
- "https://lemmy.cmstactical.net",
- "https://lemmy.cnschn.com",
- "https://lemmy.cock.social",
- "https://lemmy.codesink.io",
- "https://lemmy.coeus.icu",
- "https://lemmy.com.tr",
- "https://lemmy.comfysnug.space",
- "https://lemmy.comm.social",
- "https://lemmy.commodore.social",
- "https://lemmy.computing.zone",
- "https://lemmy.cook.gg",
- "https://lemmy.cornspace.space",
- "https://lemmy.corrigan.xyz",
- "https://lemmy.coupou.fr",
- "https://lemmy.crafty-codes.ch",
- "https://lemmy.criticalbasics.xyz",
- "https://lemmy.croc.pw",
- "https://lemmy.cronocide.net",
- "https://lemmy.cuken.net",
- "https://lemmy.cultimean.group",
- "https://lemmy.darmstadt.social",
- "https://lemmy.datatekniker.dev",
- "https://lemmy.davidbuckley.ca",
- "https://lemmy.davidfreina.at",
- "https://lemmy.dblclk.dev",
- "https://lemmy.dbzer0.com",
- "https://lemmy.dcrich.net",
- "https://lemmy.deabreu.family",
- "https://lemmy.death916.xyz",
- "https://lemmy.decronym.xyz",
- "https://lemmy.deev.io",
- "https://lemmy.dekay.se",
- "https://lemmy.demonoftheday.eu",
- "https://lemmy.design",
- "https://lemmy.devils.house",
- "https://lemmy.direktoratet.se",
- "https://lemmy.discothe.quest",
- "https://lemmy.dlgreen.com",
- "https://lemmy.dnet.social",
- "https://lemmy.doesnotexist.club",
- "https://lemmy.dogboy.xyz",
- "https://lemmy.dominikoso.me",
- "https://lemmy.donmcgin.com",
- "https://lemmy.doomeer.com",
- "https://lemmy.dormedas.com",
- "https://lemmy.douwes.co.uk",
- "https://lemmy.downcorp.tf",
- "https://lemmy.dudeami.win",
- "https://lemmy.dunkelmann.eu",
- "https://lemmy.dupper.net",
- "https://lemmy.dynatron.me",
- "https://lemmy.easfrq.live",
- "https://lemmy.eatsleepcode.ca",
- "https://lemmy.ecliptik.com",
- "https://lemmy.eco.br",
- "https://lemmy.edgarchirivella.com",
- "https://lemmy.edgeburnmedia.com",
- "https://lemmy.efradaphi.de",
- "https://lemmy.eic.lu",
- "https://lemmy.einval.net",
- "https://lemmy.eldarerathis.com",
- "https://lemmy.elest.io",
- "https://lemmy.elmusfire.xyz",
- "https://lemmy.emopolarbear.com",
- "https://lemmy.enchanted.social",
- "https://lemmy.enter-key.net",
- "https://lemmy.escapebigtech.info",
- "https://lemmy.estrogen.plus",
- "https://lemmy.eus",
- "https://lemmy.fail",
- "https://lemmy.fakecake.org",
- "https://lemmy.fanboys.xyz",
- "https://lemmy.fap.ie",
- "https://lemmy.fauxreigner.net",
- "https://lemmy.fbievan.live",
- "https://lemmy.fbxl.net",
- "https://lemmy.fdvrs.xyz",
- "https://lemmy.federate.cc",
- "https://lemmy.fedi.bub.org",
- "https://lemmy.fedihub.social",
- "https://lemmy.fediverse.jp",
- "https://lemmy.film",
- "https://lemmy.finance",
- "https://lemmy.flauschbereich.de",
- "https://lemmy.flugratte.dev",
- "https://lemmy.flunky.club",
- "https://lemmy.fmhy.ml",
- "https://lemmy.fosshost.com",
- "https://lemmy.fourbees.net",
- "https://lemmy.foxden.party",
- "https://lemmy.franciscogil.pt.eu.org",
- "https://lemmy.freddeliv.me",
- "https://lemmy.fredhs.net",
- "https://lemmy.fribyte.no",
- "https://lemmy.friheter.com",
- "https://lemmy.fromshado.ws",
- "https://lemmy.frozeninferno.xyz",
- "https://lemmy.froztbyte.dev",
- "https://lemmy.fucs.io",
- "https://lemmy.fun",
- "https://lemmy.funami.tech",
- "https://lemmy.funkyfish.cool",
- "https://lemmy.funkylab.xyz",
- "https://lemmy.fwgx.uk",
- "https://lemmy.fyi",
- "https://lemmy.g191919.com",
- "https://lemmy.g97.top",
- "https://lemmy.game-files.net",
- "https://lemmy.gamingnight.uy",
- "https://lemmy.gareth.computer",
- "https://lemmy.genkmc.de",
- "https://lemmy.giggly.de",
- "https://lemmy.gimmin.com",
- "https://lemmy.gjz010.com",
- "https://lemmy.glasgow.social",
- "https://lemmy.gmprojects.pro",
- "https://lemmy.graphics",
- "https://lemmy.graz.social",
- "https://lemmy.grenicmars.xyz",
- "https://lemmy.gross.hosting",
- "https://lemmy.grygon.com",
- "https://lemmy.gsp8181.co.uk",
- "https://lemmy.gtfo.social",
- "https://lemmy.gumpri.ch",
- "https://lemmy.hackerbots.net",
- "https://lemmy.hacktheplanet.be",
- "https://lemmy.haigner.me",
- "https://lemmy.halfbro.xyz",
- "https://lemmy.halfhosted.com",
- "https://lemmy.hamrick.xyz",
- "https://lemmy.havocperil.uk",
- "https://lemmy.helheim.net",
- "https://lemmy.helios42.de",
- "https://lemmy.hellwhore.com",
- "https://lemmy.help",
- "https://lemmy.helvetet.eu",
- "https://lemmy.heorot.uk",
- "https://lemmy.hogru.ch",
- "https://lemmy.holmosapien.com",
- "https://lemmy.hosted.frl",
- "https://lemmy.hpost.no",
- "https://lemmy.hqueue.dev",
- "https://lemmy.hugovr.dev",
- "https://lemmy.hutch.chat",
- "https://lemmy.icyserver.eu",
- "https://lemmy.id",
- "https://lemmy.insley.cloud",
- "https://lemmy.intai.tech",
- "https://lemmy.irrealis.net",
- "https://lemmy.itermori.de",
- "https://lemmy.iys.io",
- "https://lemmy.jacaranda.club",
- "https://lemmy.jamesj999.co.uk",
- "https://lemmy.jasondove.me",
- "https://lemmy.jasonsanta.xyz",
- "https://lemmy.jcaks.net",
- "https://lemmy.jcm.re",
- "https://lemmy.jengo.ca",
- "https://lemmy.jerick.xyz",
- "https://lemmy.jigoku.us.to",
- "https://lemmy.jlh.name",
- "https://lemmy.jmss.io",
- "https://lemmy.jmtr.org",
- "https://lemmy.jnks.xyz",
- "https://lemmy.johnpanos.com",
- "https://lemmy.jonaharagon.net",
- "https://lemmy.jpaulus.io",
- "https://lemmy.jpiolho.com",
- "https://lemmy.jsnordmann.de",
- "https://lemmy.jstsmthrgk.eu",
- "https://lemmy.jtmn.dev",
- "https://lemmy.juggler.jp",
- "https://lemmy.justin.rs",
- "https://lemmy.k6qw.com",
- "https://lemmy.kaelig.ovh",
- "https://lemmy.kagura.eu",
- "https://lemmy.kaouenn-noz.fr",
- "https://lemmy.karaolidis.com",
- "https://lemmy.kazsi.hu",
- "https://lemmy.kde.social",
- "https://lemmy.kemomimi.fans",
- "https://lemmy.kensand.net",
- "https://lemmy.keychat.org",
- "https://lemmy.kghorvath.com",
- "https://lemmy.khorne.me",
- "https://lemmy.kiberness.xyz",
- "https://lemmy.kilo666.com",
- "https://lemmy.kitsuna.net",
- "https://lemmy.kizaing.ca",
- "https://lemmy.ko4abp.com",
- "https://lemmy.kodeklang.social",
- "https://lemmy.korgen.xyz",
- "https://lemmy.koski.co",
- "https://lemmy.kozow.com",
- "https://lemmy.krobbel.xyz",
- "https://lemmy.krobier.com",
- "https://lemmy.kussi.me",
- "https://lemmy.kutara.io",
- "https://lemmy.kuub.io",
- "https://lemmy.kwain.net",
- "https://lemmy.kweb.ovh",
- "https://lemmy.l00p.org",
- "https://lemmy.l0nax.org",
- "https://lemmy.lantian.pub",
- "https://lemmy.legally-berlin.de",
- "https://lemmy.lemist.de",
- "https://lemmy.lettucegarden.net",
- "https://lemmy.lif.ovh",
- "https://lemmy.link",
- "https://lemmy.linuxuserspace.show",
- "https://lemmy.littleberrylodge.co.uk",
- "https://lemmy.loomy.li",
- "https://lemmy.loungerat.io",
- "https://lemmy.loutsenhizer.com",
- "https://lemmy.lpcha.im",
- "https://lemmy.lt",
- "https://lemmy.lukeog.com",
- "https://lemmy.lundgrensjostrom.com",
- "https://lemmy.m0rk.space",
- "https://lemmy.m1k.cloud",
- "https://lemmy.macaddict89.me",
- "https://lemmy.mackners.com",
- "https://lemmy.magnor.ovh",
- "https://lemmy.maisputain.ovh",
- "https://lemmy.mambastretch.com",
- "https://lemmy.management",
- "https://lemmy.maples.dev",
- "https://lemmy.mararead.com",
- "https://lemmy.marud.fr",
- "https://lemmy.mats.ooo",
- "https://lemmy.matthe815.dev",
- "https://lemmy.max-p.me",
- "https://lemmy.mazurka.xyz",
- "https://lemmy.mb-server.com",
- "https://lemmy.mbirth.uk",
- "https://lemmy.mbl.social",
- "https://lemmy.megumin.org",
- "https://lemmy.meissners.me",
- "https://lemmy.meli.dev",
- "https://lemmy.memmex.de",
- "https://lemmy.menf.in",
- "https://lemmy.meowchat.xyz",
- "https://lemmy.meridiangrp.co.uk",
- "https://lemmy.micheal65536.duckdns.org",
- "https://lemmy.miichelle.moe",
- "https://lemmy.mildgrim.com",
- "https://lemmy.minie4.de",
- "https://lemmy.minionflo.net",
- "https://lemmy.minji.xyz",
- "https://lemmy.ml",
- "https://lemmy.mlaga97.space",
- "https://lemmy.mlsn.fr",
- "https://lemmy.modshiftx.com",
- "https://lemmy.monster",
- "https://lemmy.moonling.nl",
- "https://lemmy.mooo.com",
- "https://lemmy.morrisherd.com",
- "https://lemmy.mrm.one",
- "https://lemmy.mrmonkey.xyz",
- "https://lemmy.mumbled.xyz",
- "https://lemmy.munsell.io",
- "https://lemmy.mws.rocks",
- "https://lemmy.mxh.nu",
- "https://lemmy.my.id",
- "https://lemmy.mykhoury.com",
- "https://lemmy.mypinghertz.com",
- "https://lemmy.myserv.one",
- "https://lemmy.myspamtrap.com",
- "https://lemmy.mywire.xyz",
- "https://lemmy.naga.sh",
- "https://lemmy.name",
- "https://lemmy.namwen.me",
- "https://lemmy.nauk.io",
- "https://lemmy.nbsp.one",
- "https://lemmy.neeley.cloud",
- "https://lemmy.neoluxcommunications.com",
- "https://lemmy.nerdcore.social",
- "https://lemmy.nexus",
- "https://lemmy.nikore.net",
- "https://lemmy.nine-hells.net",
- "https://lemmy.ninja",
- "https://lemmy.noogs.me",
- "https://lemmy.nope.ly",
- "https://lemmy.nopro.be",
- "https://lemmy.nowsci.com",
- "https://lemmy.nrd.li",
- "https://lemmy.nz",
- "https://lemmy.obrell.se",
- "https://lemmy.oilyeagle.com",
- "https://lemmy.omat.nl",
- "https://lemmy.one",
- "https://lemmy.onlylans.io",
- "https://lemmy.orefice.win",
- "https://lemmy.otakufarms.com",
- "https://lemmy.ourdoma.in",
- "https://lemmy.paesserver.de",
- "https://lemmy.pastwind.top",
- "https://lemmy.pathoris.de",
- "https://lemmy.pcft.eu",
- "https://lemmy.pe1uca.dev",
- "https://lemmy.pec0ra.ch",
- "https://lemmy.pen15.club",
- "https://lemmy.perigrine.ca",
- "https://lemmy.perthchat.org",
- "https://lemmy.phiresky.xyz",
- "https://lemmy.phoenix591.com",
- "https://lemmy.physfluids.fr",
- "https://lemmy.picote.ch",
- "https://lemmy.pierre-couy.fr",
- "https://lemmy.pipe01.net",
- "https://lemmy.piperservers.net",
- "https://lemmy.pipipopo.pl",
- "https://lemmy.piracy.guide",
- "https://lemmy.pit.ninja",
- "https://lemmy.place",
- "https://lemmy.plasmatrap.com",
- "https://lemmy.platypus-sandbox.com",
- "https://lemmy.podycust.co.uk",
- "https://lemmy.potatoe.ca",
- "https://lemmy.ppl.town",
- "https://lemmy.pro",
- "https://lemmy.procrastinati.org",
- "https://lemmy.productionservers.net",
- "https://lemmy.programmerhumor.io",
- "https://lemmy.pryst.de",
- "https://lemmy.pt",
- "https://lemmy.pub",
- "https://lemmy.pubsub.fun",
- "https://lemmy.pussthecat.org",
- "https://lemmy.pwarde.nl",
- "https://lemmy.pwzle.com",
- "https://lemmy.pxm.nl",
- "https://lemmy.quad442.com",
- "https://lemmy.r4r3.me",
- "https://lemmy.r6e.dev",
- "https://lemmy.radio",
- "https://lemmy.ramble.moe",
- "https://lemmy.rat.academy",
- "https://lemmy.ravc.tech",
- "https://lemmy.reckless.dev",
- "https://lemmy.recursed.net",
- "https://lemmy.remotelab.uk",
- "https://lemmy.remoteplay.im",
- "https://lemmy.rhymelikedi.me",
- "https://lemmy.richardkramer.de",
- "https://lemmy.riffel.family",
- "https://lemmy.riichi.me",
- "https://lemmy.rimkus.it",
- "https://lemmy.robotra.sh",
- "https://lemmy.rollenspiel.monster",
- "https://lemmy.ronsmans.eu",
- "https://lemmy.room409.xyz",
- "https://lemmy.roombob.cat",
- "https://lemmy.rubenernst.dev",
- "https://lemmy.run",
- "https://lemmy.ruud.je",
- "https://lemmy.s9m.xyz",
- "https://lemmy.safe-internet.org",
- "https://lemmy.saik0.com",
- "https://lemmy.samad.one",
- "https://lemmy.sascamooch.com",
- "https://lemmy.sbs",
- "https://lemmy.scam-mail.me",
- "https://lemmy.schlunker.com",
- "https://lemmy.schuerz.at",
- "https://lemmy.scootaloo.pl",
- "https://lemmy.scottlabs.io",
- "https://lemmy.scurry.io",
- "https://lemmy.sdfeu.org",
- "https://lemmy.sdfjp.org",
- "https://lemmy.sebbem.se",
- "https://lemmy.secnd.me",
- "https://lemmy.sedimentarymountains.com",
- "https://lemmy.seifert.id",
- "https://lemmy.self-hosted.site",
- "https://lemmy.selfip.org",
- "https://lemmy.servarr.com",
- "https://lemmy.server.fifthdread.com",
- "https://lemmy.serverfail.party",
- "https://lemmy.services.coupou.fr",
- "https://lemmy.sh",
- "https://lemmy.shattervideoisland.com",
- "https://lemmy.sherry.moe",
- "https://lemmy.shihaam.me",
- "https://lemmy.shinomoroll.net",
- "https://lemmy.shtuf.eu",
- "https://lemmy.shwizard.chat",
- "https://lemmy.sidh.bzh",
- "https://lemmy.sietch.online",
- "https://lemmy.sikorski.cloud",
- "https://lemmy.simpl.website",
- "https://lemmy.skillissue.dk",
- "https://lemmy.skl.works",
- "https://lemmy.slyfabi.de",
- "https://lemmy.smeargle.fans",
- "https://lemmy.smoothbrain.org",
- "https://lemmy.snoot.tube",
- "https://lemmy.socdojo.com",
- "https://lemmy.songsforno.one",
- "https://lemmy.soontm.de",
- "https://lemmy.soulfly.dk",
- "https://lemmy.spacestation14.com",
- "https://lemmy.sprawl.club",
- "https://lemmy.srv.eco",
- "https://lemmy.srv0.lol",
- "https://lemmy.st",
- "https://lemmy.staphup.nl",
- "https://lemmy.stardust.wtf",
- "https://lemmy.stark-enterprise.net",
- "https://lemmy.starless.one",
- "https://lemmy.starlightkel.xyz",
- "https://lemmy.starmade.de",
- "https://lemmy.steken.xyz",
- "https://lemmy.stellarvortex.com",
- "https://lemmy.sthorne.dev",
- "https://lemmy.stormlight.space",
- "https://lemmy.storo.social",
- "https://lemmy.stuart.fun",
- "https://lemmy.studio",
- "https://lemmy.suchmeme.nl",
- "https://lemmy.sudoer.ch",
- "https://lemmy.sumuun.net",
- "https://lemmy.svc.vesey.tech",
- "https://lemmy.sveri.de",
- "https://lemmy.swedencentral.cloudapp.azure.com",
- "https://lemmy.sweevo.net",
- "https://lemmy.swrc.dev",
- "https://lemmy.syntrofos.xyz",
- "https://lemmy.syrasu.com",
- "https://lemmy.sysctl.io",
- "https://lemmy.tabbynet.com",
- "https://lemmy.tancomps.net",
- "https://lemmy.tanktrace.de",
- "https://lemmy.tario.org",
- "https://lemmy.tarsis.org",
- "https://lemmy.teaisatfour.com",
- "https://lemmy.tealshark.net",
- "https://lemmy.tebro.fi",
- "https://lemmy.techhaven.io",
- "https://lemmy.technosorcery.net",
- "https://lemmy.techstache.com",
- "https://lemmy.tedomum.net",
- "https://lemmy.telaax.com",
- "https://lemmy.temporus.me",
- "https://lemmy.tf",
- "https://lemmy.tgxn.net",
- "https://lemmy.thanatos.at",
- "https://lemmy.the-goblin.net",
- "https://lemmy.thebias.nl",
- "https://lemmy.thecpe.xyz",
- "https://lemmy.thegoodoldinternet.com",
- "https://lemmy.theia.cafe",
- "https://lemmy.themainframe.org",
- "https://lemmy.thenullcore.com",
- "https://lemmy.theonecurly.page",
- "https://lemmy.thepixelproject.com",
- "https://lemmy.thesharpcheddar.net",
- "https://lemmy.thesilentlink.org",
- "https://lemmy.thesmokinglounge.club",
- "https://lemmy.thias.xyz",
- "https://lemmy.tillicumnet.com",
- "https://lemmy.timdn.com",
- "https://lemmy.timgilbert.be",
- "https://lemmy.timon.sh",
- "https://lemmy.timwaterhouse.com",
- "https://lemmy.tobyvin.dev",
- "https://lemmy.today",
- "https://lemmy.toldi.eu",
- "https://lemmy.toot.pt",
- "https://lemmy.tostiman.com",
- "https://lemmy.towards.vision",
- "https://lemmy.tr00st.co.uk",
- "https://lemmy.trevor.coffee",
- "https://lemmy.trippy.pizza",
- "https://lemmy.trizz.io",
- "https://lemmy.trojaner.dev",
- "https://lemmy.trumpi.co.za",
- "https://lemmy.ubergeek77.chat",
- "https://lemmy.uhhoh.com",
- "https://lemmy.umainfo.live",
- "https://lemmy.uncomfortable.business",
- "https://lemmy.unfiltered.social",
- "https://lemmy.uninsane.org",
- "https://lemmy.unknownsys.com",
- "https://lemmy.utopify.org",
- "https://lemmy.utveckla.re",
- "https://lemmy.va-11-hall-a.cafe",
- "https://lemmy.vanoverloop.xyz",
- "https://lemmy.vepta.org",
- "https://lemmy.villa-straylight.social",
- "https://lemmy.vinodjam.com",
- "https://lemmy.vip",
- "https://lemmy.virtim.dev",
- "https://lemmy.vrchat-dev.tech",
- "https://lemmy.vyizis.tech",
- "https://lemmy.w.on-t.work",
- "https://lemmy.w9r.de",
- "https://lemmy.website",
- "https://lemmy.weckhorst.no",
- "https://lemmy.weiser.social",
- "https://lemmy.weomucat.com",
- "https://lemmy.whalesinspace.de",
- "https://lemmy.whynotdrs.org",
- "https://lemmy.wiuf.net",
- "https://lemmy.wizjenkins.com",
- "https://lemmy.works",
- "https://lemmy.world",
- "https://lemmy.wraithsquadrongaming.com",
- "https://lemmy.wtf",
- "https://lemmy.wxbu.de",
- "https://lemmy.wyattsmith.org",
- "https://lemmy.x3i.tech",
- "https://lemmy.xcoolgroup.com",
- "https://lemmy.xe.net.nz",
- "https://lemmy.xoynq.com",
- "https://lemmy.zelinsky.dev",
- "https://lemmy.zell-mbc.com",
- "https://lemmy.zephyrix.com",
- "https://lemmy.zip",
- "https://lemmy.zkr.io",
- "https://lemmy.zone",
- "https://lemmy.zroot.org",
- "https://lemmy.zwanenburg.info",
- "https://lemmy2.addictmud.org",
- "https://lemmy4lemmy.com",
- "https://lemmybedan.com",
- "https://lemmydeals.com",
- "https://lemmyf.uk",
- "https://lemmyfi.com",
- "https://lemmyfly.org",
- "https://lemmygrad.ml",
- "https://lemmyis.fun",
- "https://lemmyland.com",
- "https://lemmyngton.au",
- "https://lemmynow.com",
- "https://lemmynsfw.com",
- "https://lemmyonline.com",
- "https://lemmypets.xyz",
- "https://lemmyrs.org",
- "https://lemmyunchained.net",
- "https://lemmyverse.org",
- "https://lemmywinks.com",
- "https://lemmywinks.xyz",
- "https://lemnt.telaax.com",
- "https://lemthony.com",
- "https://lemuria.es",
- "https://lemux.minnix.dev",
- "https://lib.lgbt",
- "https://libreauto.app",
- "https://liminal.southfox.me",
- "https://link.fossdle.org",
- "https://linkage.ds8.zone",
- "https://linkopath.com",
- "https://links.dartboard.social",
- "https://links.decafbad.com",
- "https://links.expressional.social",
- "https://links.hackliberty.org",
- "https://links.lowsec.club",
- "https://links.rebel.ar",
- "https://links.rocks",
- "https://links.roobre.es",
- "https://links.wageoffsite.com",
- "https://linux.community",
- "https://livesound.world",
- "https://livy.one",
- "https://lm.bittervets.org",
- "https://lm.boing.icu",
- "https://lm.byteme.social",
- "https://lm.curlefry.net",
- "https://lm.electrospek.com",
- "https://lm.gsk.moe",
- "https://lm.halfassmart.net",
- "https://lm.helilot.com",
- "https://lm.inu.is",
- "https://lm.korako.me",
- "https://lm.m0e.space",
- "https://lm.madiator.cloud",
- "https://lm.melonbread.dev",
- "https://lm.mythoranium.com",
- "https://lm.paradisus.day",
- "https://lm.put.tf",
- "https://lm.qtt.no",
- "https://lm.rdbt.no",
- "https://lm.runnerd.net",
- "https://lm.sethp.cc",
- "https://lm.suitwaffle.com",
- "https://lm.sysv.dev",
- "https://lm.thesqooid.com",
- "https://lm.williampuckering.com",
- "https://lmmy.io",
- "https://lmmy.net",
- "https://lmmy.tvdl.dev",
- "https://lmmy.ylwsgn.cc",
- "https://lmy.axi.cx",
- "https://lmy.dotcomitsa.website",
- "https://lmy.mymte.de",
- "https://lmy.singinwhale.com",
- "https://local106.com",
- "https://lolimbeer.com",
- "https://lostcheese.com",
- "https://lsmu.schmurian.xyz",
- "https://lululemmy.com",
- "https://lurk.fun",
- "https://mander.xyz",
- "https://marginalcuriosity.net",
- "https://matejc.com",
- "https://matts.digital",
- "https://meganice.online",
- "https://melly.0x-ia.moe",
- "https://merv.news",
- "https://mesita.link",
- "https://metapowers.org",
- "https://mh.znark.us",
- "https://mhl.onl",
- "https://midwest.social",
- "https://milksteak.org",
- "https://mimiclem.me",
- "https://mindshare.space",
- "https://mlem.a-smol-cat.fr",
- "https://mlem.lea.moe",
- "https://mobilemmohub.com",
- "https://monero.town",
- "https://monyet.cc",
- "https://moose.best",
- "https://moot.place",
- "https://moto.teamswollen.org",
- "https://mtgzone.com",
- "https://mujico.org",
- "https://mylem.eu",
- "https://mylem.me",
- "https://mylem.my",
- "https://mylemmy.win",
- "https://narod.city",
- "https://nc.gnzl.cl",
- "https://negativenull.com",
- "https://netmonkey.tech",
- "https://news.cosocial.ca",
- "https://news.deghg.org",
- "https://news.idlestate.org",
- "https://nlemmy.nl",
- "https://no.lastname.nz",
- "https://nonewfriends.club",
- "https://normalcity.life",
- "https://not-enough-sci.fi",
- "https://notdigg.com",
- "https://notlemmy.notawebsite.fr",
- "https://notyour.rodeo",
- "https://novoidspace.com",
- "https://nrsk.no",
- "https://nunu.dev",
- "https://nwdr.club",
- "https://occult.social",
- "https://oceanbreeze.earth",
- "https://odin.lanofthedead.xyz",
- "https://omg.qa",
- "https://on.syrma.cc",
- "https://opendmz.social",
- "https://orava.dev",
- "https://orzen.games",
- "https://ou0.de",
- "https://outpost.zeuslink.net",
- "https://overctrl.dbzer0.com",
- "https://parapheum.com",
- "https://partizle.com",
- "https://pathfinder.social",
- "https://pathofexile-discuss.com",
- "https://pawb.social",
- "https://pcglinks.com",
- "https://philly.page",
- "https://plork.monster",
- "https://pootusmaximus.xyz",
- "https://popplesburger.hilciferous.nl",
- "https://poptalk.scrubbles.tech",
- "https://possumpat.io",
- "https://posta.no",
- "https://postit.quantentoast.de",
- "https://preserve.games",
- "https://pricefield.org",
- "https://prime8s.xyz",
- "https://programming.dev",
- "https://proit.org",
- "https://psychedelia.ink",
- "https://purrito.kamartaj.xyz",
- "https://quex.cc",
- "https://quo.ink",
- "https://r-sauna.fi",
- "https://r.dcotta.eu",
- "https://r.gir.st",
- "https://r.rosettast0ned.com",
- "https://rabbitea.rs",
- "https://radiation.party",
- "https://rammy.site",
- "https://rational-racoon.de",
- "https://rblind.com",
- "https://rc.liftoff-app.org",
- "https://rdr.lol",
- "https://re.tei.li",
- "https://read.widerweb.org",
- "https://red.cyberhase.de",
- "https://reddit.moonbeam.town",
- "https://reddrefuge.com",
- "https://reddthat.com",
- "https://rekabu.ru",
- "https://reseed.it",
- "https://retarded.dev",
- "https://ripo.st",
- "https://rlyeh.cc",
- "https://rlyeh.icu",
- "https://roznotech.xyz",
- "https://rustyshackleford.cfd",
- "https://s.itskhanow.com",
- "https://s.jape.work",
- "https://s0ss.net",
- "https://sambaspy.com",
- "https://scif6.nsalanparty.com",
- "https://sedd.it",
- "https://seemel.ink",
- "https://selfhosted.forum",
- "https://sffa.community",
- "https://sh.itjust.works",
- "https://sha1.nl",
- "https://shinobu.cloud",
- "https://shitposting.monster",
- "https://shork.online",
- "https://sideone.co.uk",
- "https://sigmet.io",
- "https://skwerl.dev",
- "https://slangenettet.pyjam.as",
- "https://slrpnk.net",
- "https://sneakernet.social",
- "https://snkkis.me",
- "https://snuv.win",
- "https://soccer.forum",
- "https://social.belowland.com",
- "https://social.coalition.space",
- "https://social.cyb3r.dog",
- "https://social.dn42.us",
- "https://social.fossware.space",
- "https://social.fr4me.io",
- "https://social.ggbox.fr",
- "https://social.hamington.net",
- "https://social.jears.at",
- "https://social.nerdhouse.io",
- "https://social.poisson.me",
- "https://social.sour.is",
- "https://social.styxem.xyz",
- "https://social.vmdk.ca",
- "https://solstice.etbr.top",
- "https://sopuli.xyz",
- "https://spgrn.com",
- "https://stable.liftoff-app.org",
- "https://stammtisch.hallertau.social",
- "https://stanx.page",
- "https://startrek.website",
- "https://sub.rdls.dev",
- "https://sub.wetshaving.social",
- "https://sublight.one",
- "https://sudood.us",
- "https://suguha.net",
- "https://sullen.social",
- "https://superdark.social",
- "https://suppo.fi",
- "https://support.futbol",
- "https://surlesworld.com",
- "https://surom.de",
- "https://switter.su",
- "https://szmer.info",
- "https://t.bobamilktea.xyz",
- "https://tabletop.place",
- "https://tagpro.lol",
- "https://talk.kururin.tech",
- "https://talka.live",
- "https://techy.news",
- "https://terefere.eu",
- "https://textandmetal.com",
- "https://tezzo.f0rk.pl",
- "https://thaumatur.ge",
- "https://thechurchofmemes.com",
- "https://theculture.social",
- "https://thediscussion.site",
- "https://thegarden-u4873.vm.elestio.app",
- "https://thegarden.land",
- "https://thelemmy.club",
- "https://theotter.social",
- "https://thepride.hexodine.com",
- "https://thesidewalkends.io",
- "https://thesimplecorner.org",
- "https://thevapor.space",
- "https://tkohhh.social",
- "https://toast.ooo",
- "https://toons.zone",
- "https://tortoisewrath.com",
- "https://tslemmy.duckdns.org",
- "https://ttrpg.network",
- "https://tucson.social",
- "https://typemi.me",
- "https://upvote.au",
- "https://va11halla.bar",
- "https://vlemmy.net",
- "https://voltage.vn",
- "https://voxpop.social",
- "https://voyager.alec.is",
- "https://voyager.lemmy.ml",
- "https://wallstreets.bet",
- "https://waveform.social",
- "https://wayfarershaven.eu",
- "https://werm.social",
- "https://whata.clusterfsck.com",
- "https://whiskers.bim.boats",
- "https://wilbo.tech",
- "https://wirebase.org",
- "https://wired.bluemarch.art",
- "https://wizanons.dev",
- "https://wumbo.buzz",
- "https://www.jrz.city",
- "https://www.korzekwa.io",
- "https://xbdv.com",
- "https://xcore.social",
- "https://xffxe4.lol",
- "https://xrs.cx",
- "https://yakiak.com",
- "https://yall.theatl.social",
- "https://yamasaur.com",
- "https://yiffit.net",
- "https://ymmel.nl",
- "https://yogibytes.page",
- "https://zemmy.cc",
- "https://zen.lema.cl",
- "https://zeronull.xyz",
- "https://zoo.splitlinux.org"
- ]);
- var INSTANCES_KBIN = /* @__PURE__ */ new Set([
- "https://1001.coolest.zone",
- "https://baguette.pub",
- "https://bin.pol.social",
- "https://community.yshi.org",
- "https://feddit.online",
- "https://fedi196.gay",
- "https://fedia.io",
- "https://fediverse.boo",
- "https://forum.fail",
- "https://fr3diver.se",
- "https://gehirneimer.de",
- "https://jlailu.social",
- "https://k.fe.derate.me",
- "https://karab.in",
- "https://kayb.ee",
- "https://kbin.buzz",
- "https://kbin.cafe",
- "https://kbin.chat",
- "https://kbin.dk",
- "https://kbin.donar.dev",
- "https://kbin.ectolab.net",
- "https://kbin.fedi.cr",
- "https://kbin.holmosapien.com",
- "https://kbin.korgen.xyz",
- "https://kbin.lgbt",
- "https://kbin.lol",
- "https://kbin.melroy.org",
- "https://kbin.nz",
- "https://kbin.place",
- "https://kbin.primitivebits.social",
- "https://kbin.projectsegfau.lt",
- "https://kbin.rocks",
- "https://kbin.run",
- "https://kbin.sh",
- "https://kbin.social",
- "https://kbin.tech",
- "https://kbin.thicknahalf.com",
- "https://kilioa.org",
- "https://kopnij.in",
- "https://longley.ws",
- "https://nadajnik.org",
- "https://nerdbin.social",
- "https://no.faux.moe",
- "https://nolani.academy",
- "https://open-source.social",
- "https://readit.buzz",
- "https://remy.city",
- "https://social.tath.link",
- "https://socialnetworks.rodeo",
- "https://streetbikes.club",
- "https://the.coolest.zone",
- "https://thebrainbin.org",
- "https://tuna.cat",
- "https://vdcw.social",
- "https://wiku.hu",
- "https://www.fedia.io"
- ]);
- trace(`Define instances sets end`);
-
- // src/our-changes.js
- var OUR_CHANGES = { addedNodes: {} };
- function getAddedNodesSelectors() {
- return Object.values(OUR_CHANGES.addedNodes);
- }
- function registerAddedNode(id, selector) {
- OUR_CHANGES.addedNodes[id] = selector;
- }
-
- // src/constants.js
- var constants_default = {
- ICON_CLASS: withNS(`icon`),
- ICON_LOADING_CLASS: withNS(`loading`),
- ICON_STYLES_ID: withNS(`icon-styles`),
- ICON_LINK_CLASS: withNS(`icon-link`),
- ICON_LINK_SYMBOL_ID: withNS(`icon-link-symbol`),
- ICON_SPINNER_CLASS: withNS(`icon-spinner`),
- ICON_SPINNER_SYMBOL_ID: withNS(`icon-spinner-symbol`),
- ORIGINAL_LINK_CLASS: withNS(`original-link`),
- SHOW_AT_HOME_BUTTON_CLASS: withNS(`show-at-home`),
- MAKE_HOME_BUTTON_ID: withNS(`make-home`),
- ICON_SVG_TEMPLATE_ID: withNS(`icon-template`),
- AUTH_WRONG: `AUTH_WRONG`,
- AUTH_MISSING: `AUTH_MISSING`,
- REWRITE_STATUS: withNSCamelCase(`localUrlStatus`),
- REWRITE_STATUS_PENDING: `pending`,
- REWRITE_STATUS_SUCCESS: `success`,
- REWRITE_STATUS_ERROR: `error`,
- REWRITE_STATUS_UNRESOLVED: `unresolved`,
- SETUP_AUTH_MESSAGE: `Lemmy Universal Link Switcher: Visit your home instance once to set up post/comment rewriting`
- };
- function withNS(identifier) {
- return `lemmy-rewrite-urls-` + identifier;
- }
- function withNSCamelCase(identifier) {
- return `lemmyRewriteUrls` + identifier.charAt(0).toUpperCase() + identifier.slice(1);
- }
-
- // src/rewriting/helpers.js
- function isHashLink(link) {
- return link.hash && link.origin + link.pathname + link.search === location.origin + location.pathname + location.search;
- }
- function isSamePage(url1, url2) {
- return url1.host === url2.host && url1.pathname === url2.pathname;
- }
- function isV17() {
- return isoData?.site_res?.version.startsWith(`0.17`);
- }
- var stopEventHandler = (event) => {
- event.preventDefault();
- event.stopPropagation();
- };
-
- // src/gm.js
- async function setValue(key, value) {
- trace(`GM.setValue key ${key}, value ${value}`);
- await GM.setValue(key, value);
- }
- async function getValue(key) {
- return await GM.getValue(key);
- }
- function parseResponse(response) {
- try {
- return JSON.parse(response.response);
- } catch (e) {
- debug(`Error parsing response JSON`, e);
- return response.response;
- }
- }
- function logRequest(response, data) {
- trace(
- `FinalUrl`,
- response.finalUrl,
- `status`,
- response.status,
- `text`,
- response.statusText,
- `response`,
- data || response.response
- );
- trace(`responseHeaders`, response.responseHeaders);
- }
- function performXmlHttpRequest(url, doneCallback) {
- GM.xmlHttpRequest({
- url,
- onloadend: (response) => {
- const data = parseResponse(response);
- logRequest(response, data);
- doneCallback(response, data);
- }
- });
- }
-
- // src/rewriting/auth.js
- var AUTH;
- function getAuthFromCookie() {
- return document.cookie.split("; ").find((row) => row.startsWith("jwt="))?.split("=")[1];
- }
- async function setAuth(auth) {
- AUTH = auth;
- await setValue(`auth`, auth);
- }
- async function initAuth() {
- const curAuth = await getAuth();
- if (curAuth) {
- AUTH = curAuth;
- return;
- }
- if (location.origin === HOME) {
- const newAuth = getAuthFromCookie();
- await setAuth(newAuth);
- if (newAuth && await getValue(`authNoticeShown`)) {
- alert(`Lemmy Universal Link Switcher: Post/comment rewriting has been set up successfully`);
- await setValue(`authNoticeShown`, null);
- }
- } else if (HOME && !await getValue(`authNoticeShown`)) {
- await setValue(`authNoticeShown`, `true`);
- alert(constants_default.SETUP_AUTH_MESSAGE);
- }
- }
- function updateAuthPeriodically() {
- setInterval(async () => {
- const prev = AUTH;
- const newAuth = location.origin === HOME ? getAuthFromCookie() : await getAuth();
- if (prev !== newAuth) {
- debug(`Auth changed`);
- await setAuth(newAuth);
- clearMissingUrlsInCache();
- triggerRewrite();
- }
- }, 1234);
- }
- async function getAuth() {
- return await getValue(`auth`);
- }
-
- // src/rewriting/url-mapping.js
- function splitPaths(url) {
- return url.pathname.split(`/`).slice(1);
- }
- function isRemoteLemmyUrl(url) {
- return url.origin !== HOME && isLemmyInstance(url);
- }
- function isRemoteKbinUrl(url) {
- return url.origin !== HOME && isKbinInstance(url);
- }
- function isRemoteUrl(url) {
- return isRemoteLemmyUrl(url) || isRemoteKbinUrl(url);
- }
- function findLocalUrlForStandardAtFormat(url, rootPath) {
- const paths = splitPaths(url);
- const name = paths[1].includes(`@`) ? paths[1] : paths[1] + `@` + url.host;
- return `${HOME}/${rootPath || paths[0]}/${name}` + url.search + url.hash;
- }
- function findLocalUrlForLemmyUrl(url) {
- if (isLemmyUserOrCommunityUrl(url)) {
- return findLocalUrlForStandardAtFormat(url);
- } else {
- return null;
- }
- }
- function findLocalUrlForKbinUserUrl(url) {
- const paths = splitPaths(url);
- const user = paths[1].startsWith(`@`) ? paths[1].substring(1) : paths[1];
- const name = user.includes(`@`) ? user : user + `@` + url.host;
- return `${HOME}/u/${name}` + url.search + url.hash;
- }
- function findLocalUrlForKbinUrl(url) {
- if (isKbinMagazineUrl(url)) {
- return findLocalUrlForStandardAtFormat(url, mappedKbinRootPath(url));
- } else if (isKbinUserUrl(url)) {
- return findLocalUrlForKbinUserUrl(url);
- } else {
- return null;
- }
- }
- function findLocalUrl(url) {
- if (isRemoteLemmyUrl(url))
- return findLocalUrlForLemmyUrl(url);
- if (isRemoteKbinUrl(url))
- return findLocalUrlForKbinUrl(url);
- return null;
- }
- async function fetchApIdFromRemote(url) {
- const endpoint = isLemmyPostUrl(url) ? `post` : `comment`;
- const paths = splitPaths(url);
- const id = paths[1];
- return new Promise((resolve, reject) => {
- performXmlHttpRequest(`${url.origin}/api/v3/${endpoint}?id=${id}`, (response, data) => {
- const apId = data[`${endpoint}_view`]?.[endpoint]?.ap_id;
- if (response.status === 200 && apId) {
- resolve(apId);
- } else {
- handleFailedRequest(`fetching AP ID`, response, reject);
- }
- });
- });
- }
- function handleFailedRequest(requestName, response, reject) {
- if (response.status >= 200 && response.status <= 299) {
- reject(`${requestName}: Unhandled successful response, status: ${response.status}`);
- } else if (response.status >= 400 && response.status <= 599) {
- reject(`${requestName}: Error, status: ${response.status}`);
- } else {
- reject(`${requestName}: Something weird happened, status: ${response.status}`);
- }
- }
- async function resolveObjectFromHome(url) {
- return new Promise(async (resolve, reject) => {
- const auth = await getAuth();
- if (!auth) {
- debug(`No auth token found`);
- reject(constants_default.AUTH_MISSING);
- }
- performXmlHttpRequest(
- `${HOME}/api/v3/resolve_object?auth=${auth}&q=${encodeURIComponent(url.href)}`,
- (response, data) => {
- if (response.status === 200 && data.post?.post?.id) {
- resolve(`${HOME}/post/${data.post.post.id}${url.search}${url.hash}`);
- } else if (response.status === 200 && data.comment?.comment?.id) {
- resolve(`${HOME}/comment/${data.comment.comment.id}${url.search}${url.hash}`);
- } else if (response.status === 400 && data?.error === `couldnt_find_object`) {
- resolve(null);
- } else if (response.status === 400 && data?.error === `not_logged_in`) {
- reject(constants_default.AUTH_WRONG);
- } else {
- handleFailedRequest(`resolving object`, response, reject);
- }
- }
- );
- });
- }
- var urlCache = {};
- function clearMissingUrlsInCache() {
- for (const value of Object.values(urlCache)) {
- if (value.error)
- delete value.error;
- if (value.localUrl === null)
- delete value.localUrl;
- }
- }
- function getCacheKey(url) {
- return url.host + url.pathname + url.search;
- }
- function cacheResult(url, localUrl) {
- const key = getCacheKey(url);
- if (!urlCache[key]) {
- urlCache[key] = {};
- }
- if (urlCache[key].error)
- delete urlCache[key].error;
- urlCache[key].localUrl = localUrl;
- return localUrl;
- }
- function cacheErrorResult(url, error) {
- const key = getCacheKey(url);
- if (!urlCache[key]) {
- urlCache[key] = {};
- }
- urlCache[key].error = error;
- }
- function getLocalUrlfromCache(url) {
- const key = getCacheKey(url);
- if (urlCache[key]?.error) {
- throw urlCache[key]?.error;
- } else {
- return urlCache[key]?.localUrl;
- }
- }
- async function fetchLocalUrl(url, loadFromCache = true) {
- if (loadFromCache) {
- const cached = getLocalUrlfromCache(url);
- if (cached !== void 0) {
- trace(`Found URL ${url} in cache: ${cached}`);
- return cached;
- }
- }
- try {
- return cacheResult(url, await fetchLocalUrlNoCache(url));
- } catch (e) {
- debug(`fetchLocalUrl error`, e);
- cacheErrorResult(url, e);
- throw e;
- }
- }
- async function fetchLocalUrlNoCache(url) {
- trace(`Trying to resolve URL ${url} directly`);
- const localUrl = await resolveObjectFromHome(url);
- if (localUrl !== null) {
- return localUrl;
- } else {
- trace(`Did not find URL ${url} directly`);
- }
- const apId = new URL(await fetchApIdFromRemote(url));
- trace(`Found AP ID for URL ${url}: ${apId}`);
- if (!apId.search) {
- apId.search = url.search;
- }
- if (!apId.hash) {
- apId.hash = url.hash;
- }
- if (isSamePage(url, apId)) {
- trace(`Previous URL was AP ID already, URL not federated for some reason`);
- return null;
- } else {
- return await resolveObjectFromHome(apId);
- }
- }
- function isInstantlyRewritable(url) {
- return isRemoteLemmyUrl(url) && isLemmyUserOrCommunityUrl(url) || isRemoteKbinUrl(url) && (isKbinMagazineUrl(url) || isKbinUserUrl(url));
- }
- function isRewritableAfterResolving(url) {
- return isRemoteLemmyUrl(url) && (isLemmyPostUrl(url) || isLemmyCommentUrl(url));
- }
- function isLemmyPostUrl(url) {
- const paths = splitPaths(url);
- return paths[0] === `post`;
- }
- function isLemmyCommentUrl(url) {
- const paths = splitPaths(url);
- return paths[0] === `comment`;
- }
- function isLemmyUserOrCommunityUrl(url) {
- const paths = splitPaths(url);
- return paths[0] === `c` || paths[0] === `u`;
- }
- function isKbinPostUrl(url) {
- const paths = splitPaths(url);
- return paths[0] === `m` && paths.length > 2 && paths[2] === `t`;
- }
- function isKbinMicroblogUrl(url) {
- const paths = splitPaths(url);
- return paths[0] === `m` && paths.length > 2 && paths[2] === `p`;
- }
- function isKbinMicroblogOverviewUrl(url) {
- const paths = splitPaths(url);
- return paths[0] === `m` && paths.length > 2 && paths[2] === `microblog`;
- }
- function isKbinMagazinePeopleUrl(url) {
- const paths = splitPaths(url);
- return paths[0] === `m` && paths.length > 2 && paths[2] === `people`;
- }
- function isKbinMagazineUrl(url) {
- const paths = splitPaths(url);
- return paths[0] === `m` && !isKbinPostUrl(url) && !isKbinMagazinePeopleUrl(url) && !isKbinMicroblogUrl(url) && !isKbinMicroblogOverviewUrl(url);
- }
- function mappedKbinRootPath(url) {
- const paths = splitPaths(url);
- if (paths[0] === `m`) {
- return `c`;
- } else {
- return null;
- }
- }
- function isKbinUserUrl(url) {
- const paths = splitPaths(url);
- return paths.length === 2 && paths[0] === `u`;
- }
-
- // src/rewriting/links/icon.js
- function getIcon(link) {
- return link.querySelector(`.` + constants_default.ICON_CLASS);
- }
- function createIcon(link) {
- ensureTemplateAvailable();
- ensureIconStylesAdded();
- const wrapper = document.createElement(`span`);
- registerAddedNode(constants_default.ICON_CLASS, `.` + constants_default.ICON_CLASS);
- wrapper.classList.add(constants_default.ICON_CLASS);
- if (link.children.length === 0 || getComputedStyle(link.children[link.children.length - 1]).marginRight === `0px`) {
- wrapper.style.marginLeft = `0.5em`;
- }
- const linkIcon = createSVG();
- linkIcon.classList.add(constants_default.ICON_LINK_CLASS);
- linkIcon.innerHTML = `<use href=#${constants_default.ICON_LINK_SYMBOL_ID} />`;
- wrapper.append(linkIcon);
- const spinnerIcon = createSVG();
- spinnerIcon.classList.add(constants_default.ICON_SPINNER_CLASS);
- spinnerIcon.innerHTML = `<use href=#${constants_default.ICON_SPINNER_SYMBOL_ID} />`;
- wrapper.append(spinnerIcon);
- return wrapper;
- }
- function createSVG() {
- return document.createElementNS(`http://www.w3.org/2000/svg`, `svg`);
- }
- function ensureTemplateAvailable() {
- if (document.querySelector(`#` + constants_default.ICON_SVG_TEMPLATE_ID))
- return;
- const template = createSVG();
- template.id = constants_default.ICON_SVG_TEMPLATE_ID;
- template.innerHTML = `<defs>
- <symbol id=${constants_default.ICON_LINK_SYMBOL_ID} viewBox="0 0 100 100"><path d="M52.8 34.6c.8.8 1.8 1.2 2.8 1.2s2-.4 2.8-1.2c1.5-1.5 1.5-4 0-5.6l-5.2-5.2h26v30.6c0 2.2 1.8 3.9 3.9 3.9 2.2 0 3.9-1.8 3.9-3.9V19.8c0-2.2-1.8-3.9-3.9-3.9h-30l5.2-5.2c1.5-1.5 1.5-4 0-5.6s-4-1.5-5.6 0l-11.8 12c-1.5 1.5-1.5 4 0 5.6l11.9 11.9zM31.1 28.7V11c0-3-2.5-5.5-5.5-5.5H8C5 5.5 2.5 8 2.5 11v17.7c0 3 2.5 5.5 5.5 5.5h17.7c3 0 5.4-2.5 5.4-5.5zM47.2 65.4c-1.5-1.5-4-1.5-5.6 0s-1.5 4 0 5.6l5.2 5.2h-26V45.6c0-2.2-1.8-3.9-3.9-3.9S13 43.5 13 45.6v34.5c0 2.2 1.8 3.9 3.9 3.9h30l-5.2 5.2c-1.5 1.5-1.5 4 0 5.6.8.8 1.8 1.2 2.8 1.2s2-.4 2.8-1.2l11.9-11.9c1.5-1.5 1.5-4 0-5.6l-12-11.9zM92 65.8H74.4c-3 0-5.5 2.5-5.5 5.5V89c0 3 2.5 5.5 5.5 5.5H92c3 0 5.5-2.5 5.5-5.5V71.3c0-3-2.5-5.5-5.5-5.5z"/></symbol>
- <symbol id=${constants_default.ICON_SPINNER_SYMBOL_ID} viewBox="0 0 32 32"><path d="M16 32c-4.274 0-8.292-1.664-11.314-4.686s-4.686-7.040-4.686-11.314c0-3.026 0.849-5.973 2.456-8.522 1.563-2.478 3.771-4.48 6.386-5.791l1.344 2.682c-2.126 1.065-3.922 2.693-5.192 4.708-1.305 2.069-1.994 4.462-1.994 6.922 0 7.168 5.832 13 13 13s13-5.832 13-13c0-2.459-0.69-4.853-1.994-6.922-1.271-2.015-3.066-3.643-5.192-4.708l1.344-2.682c2.615 1.31 4.824 3.313 6.386 5.791 1.607 2.549 2.456 5.495 2.456 8.522 0 4.274-1.664 8.292-4.686 11.314s-7.040 4.686-11.314 4.686z"/></symbol>
- </defs>`;
- registerAddedNode(constants_default.ICON_SVG_TEMPLATE_ID, `#` + constants_default.ICON_SVG_TEMPLATE_ID);
- document.head.append(template);
- }
- function ensureIconStylesAdded() {
- if (document.querySelector(`#` + constants_default.ICON_STYLES_ID))
- return;
- const style = document.createElement(`style`);
- style.id = constants_default.ICON_STYLES_ID;
- style.innerHTML = `
- .${constants_default.ICON_SPINNER_CLASS} {
- display: none;
- animation: spins 2s linear infinite;
- }
- .${constants_default.ICON_LINK_CLASS} {
- display: inline-block;
- }
- .${constants_default.ICON_LOADING_CLASS} > .${constants_default.ICON_LINK_CLASS} {
- display: none;
- }
- .${constants_default.ICON_LOADING_CLASS} > .${constants_default.ICON_SPINNER_CLASS} {
- display: inline-block;
- }
- .${constants_default.ICON_CLASS} > svg {
- vertical-align: sub;
- height: 1em; width: 1em;
- stroke: currentColor;
- fill: currentColor;
- }`;
- registerAddedNode(constants_default.ICON_STYLES_ID, `#` + constants_default.ICON_STYLES_ID);
- document.head.append(style);
- }
-
- // src/tippy.js
- var tippy_default = window.tippy;
-
- // src/rewriting/links/tooltip.js
- function getOriginalLinkHtml(originalHref) {
- registerAddedNode(constants_default.ORIGINAL_LINK_CLASS, `.` + constants_default.ORIGINAL_LINK_CLASS);
- return `Original link: <a class="${constants_default.ORIGINAL_LINK_CLASS}" href="${originalHref}">${originalHref}</a>`;
- }
- function defaultOptions(link) {
- return {
- appendTo: () => link.parentNode,
- allowHTML: true,
- interactive: true,
- animation: false,
- placement: "bottom",
- hideOnClick: false
- };
- }
- function createOriginalLinkTooltip(link, originalHref) {
- trace(`Create original link tooltip`, link, originalHref);
- getIcon(link).addEventListener(`click`, stopEventHandler);
- return createLinkTooltip(link, getOriginalLinkHtml(originalHref));
- }
- function createLinkTooltip(link, content) {
- return tippy_default(getIcon(link), {
- ...defaultOptions(link),
- content
- });
- }
- function createLinkLoadTooltip(link) {
- trace(`Create link load tooltip`, link);
- getIcon(link).classList.add(constants_default.ICON_LOADING_CLASS);
- return createLinkTooltip(link, `Loading home URL...<br />Don't want to wait? ${getOriginalLinkHtml(link.href)}`);
- }
- function linkLoadTooltipSuccess(tooltip, originalHref) {
- linkLoadResult(tooltip, `\u2714\uFE0F Changed link to home instance`, getOriginalLinkHtml(originalHref));
- }
- function linkLoadTooltipError(tooltip, error) {
- linkLoadResult(tooltip, `\u274C ` + error);
- }
- function linkLoadResult(tooltip, result, finalContent = result) {
- const icon = tooltip.reference;
- icon.classList.remove(constants_default.ICON_LOADING_CLASS);
- icon.addEventListener(`click`, stopEventHandler);
- if (tooltip.state.isVisible) {
- tooltip.setContent(result);
- setTimeout(() => {
- tooltip.hide();
- tooltip.setContent(finalContent);
- }, 2e3);
- } else {
- tooltip.setContent(finalContent);
- }
- }
-
- // src/rewriting/links/links.js
- function changeLinkHref(link, localUrl) {
- const treeWalker = document.createTreeWalker(link, NodeFilter.SHOW_TEXT, (node) => {
- if (node.textContent.toLowerCase().trim() === link.href.toLowerCase().trim()) {
- return NodeFilter.FILTER_ACCEPT;
- } else {
- return NodeFilter.FILTER_SKIP;
- }
- });
- let textNode;
- while ((textNode = treeWalker.nextNode()) !== null) {
- textNode.textContent = localUrl;
- }
- link.href = localUrl;
- link.addEventListener(`click`, (event) => {
- if (event.button === 0 && !event.ctrlKey && link.target !== `_blank`) {
- location.href = localUrl;
- }
- });
- }
- function appendIconTo(elem, icon) {
- if (elem.children.length === 0 || getComputedStyle(elem.children[elem.children.length - 1]).display !== `inline-block`) {
- elem.append(icon);
- } else {
- appendIconTo(elem.children[elem.children.length - 1], icon);
- }
- }
- function addFetchLocalUrlHandler(link) {
- let tooltip;
- const handler = async (event) => {
- if (event.type === `click`) {
- stopEventHandler(event);
- if (tooltip)
- tooltip.show();
- return;
- }
- link.removeEventListener(`focus`, handler);
- link.removeEventListener(`mouseenter`, handler);
- if (link.dataset[constants_default.REWRITE_STATUS] === constants_default.REWRITE_STATUS_PENDING)
- return;
- link.dataset[constants_default.REWRITE_STATUS] = constants_default.REWRITE_STATUS_PENDING;
- tooltip = createLinkLoadTooltip(link);
- try {
- const localUrl = await fetchLocalUrl(link);
- if (!localUrl) {
- debug(`Local URL for ${link.href} could not be found`);
- linkLoadTooltipError(tooltip, `Home URL could not be found`);
- return;
- }
- trace(`Local URL for ${link.href} found: ${localUrl}`);
- const oldHref = link.href;
- changeLinkHref(link, localUrl);
- linkLoadTooltipSuccess(tooltip, oldHref);
- link.dataset[constants_default.REWRITE_STATUS] = constants_default.REWRITE_STATUS_SUCCESS;
- } catch (e) {
- debug(`Error while trying to resolve local URL`, e);
- let msg;
- if (e === constants_default.AUTH_WRONG) {
- msg = `Saved login expired. Return to your home instance and log in again.`;
- } else if (e === constants_default.AUTH_MISSING) {
- msg = constants_default.SETUP_AUTH_MESSAGE;
- } else {
- msg = `Error while trying to find home URL`;
- }
- linkLoadTooltipError(tooltip, msg);
- link.dataset[constants_default.REWRITE_STATUS] = constants_default.REWRITE_STATUS_ERROR;
- } finally {
- link.removeEventListener(`click`, handler);
- }
- };
- link.addEventListener(`click`, handler);
- link.addEventListener(`focus`, handler);
- link.addEventListener(`mouseenter`, handler);
- }
- function isFediverseLink(link) {
- const svg = link.querySelector(`svg`);
- if (!svg)
- return false;
- if (svg.children.length === 0)
- return false;
- return svg.children[0].getAttribute(`xlink:href`)?.includes(`#icon-fedilink`);
- }
- function rewriteToLocal(link) {
- if (!link.parentNode)
- return false;
- if (link.classList.contains(constants_default.ORIGINAL_LINK_CLASS))
- return false;
- if (link.dataset[constants_default.REWRITE_STATUS] === constants_default.REWRITE_STATUS_SUCCESS)
- return false;
- if (isHashLink(link))
- return false;
- if (!isRemoteUrl(link))
- return false;
- if (isFediverseLink(link))
- return false;
- if (isInstantlyRewritable(link)) {
- const localUrl = findLocalUrl(link);
- if (!localUrl)
- return false;
- if (isSamePage(new URL(localUrl), location))
- return false;
- const oldHref = link.href;
- changeLinkHref(link, localUrl);
- const icon = createIcon(link);
- appendIconTo(link, icon);
- createOriginalLinkTooltip(link, oldHref);
- link.dataset[constants_default.REWRITE_STATUS] = constants_default.REWRITE_STATUS_SUCCESS;
- trace(`Rewrite link`, link, ` from`, oldHref, `to`, localUrl);
- return true;
- } else if (isRewritableAfterResolving(link)) {
- if (!getIcon(link)) {
- appendIconTo(link, createIcon(link));
- }
- if (!link.dataset[constants_default.REWRITE_STATUS]) {
- link.dataset[constants_default.REWRITE_STATUS] = constants_default.REWRITE_STATUS_UNRESOLVED;
- addFetchLocalUrlHandler(link);
- }
- }
- }
- function findLinksInChange(change) {
- if (change.type === `childList`) {
- const links = Array.from(change.addedNodes).flatMap((addedNode) => {
- if (addedNode.tagName?.toLowerCase() === `a`) {
- return addedNode;
- } else if (addedNode.querySelectorAll) {
- return Array.from(addedNode.querySelectorAll(`a`));
- } else {
- return [];
- }
- });
- if (links.length > 0)
- trace(`Change`, change, `contained the links`, links);
- return links;
- } else if (change.type === `attributes`) {
- return change.target.matches?.(`a`) ? change.target : [];
- } else {
- return [];
- }
- }
- function findLinksToRewrite(changes) {
- if (!changes) {
- return document.querySelectorAll(`a`);
- }
- return changes.flatMap(findLinksInChange);
- }
- async function rewriteLinksToLocal(changes) {
- const links = findLinksToRewrite(changes);
- const chunkSize = 50;
- return await async function processChunk(currentChunk) {
- const startIdx = currentChunk * chunkSize;
- const endChunkIdx = (currentChunk + 1) * chunkSize;
- const endIdx = Math.min(links.length, endChunkIdx);
- debug(
- `Processing ${links.length} links, current chunk `,
- currentChunk,
- `processing links ${startIdx} to ${endIdx}`
- );
- let anyRewritten = false;
- for (let i = startIdx; i < endIdx; ++i) {
- const rewritten = rewriteToLocal(links[i]);
- anyRewritten = anyRewritten || rewritten;
- }
- debug(`Processed links ${startIdx} to ${endIdx}`);
- if (endChunkIdx >= links.length) {
- return anyRewritten;
- }
- const chunkResult = await new Promise((resolve) => setTimeout(async () => {
- resolve(await processChunk(currentChunk + 1));
- }, 0));
- return anyRewritten || chunkResult;
- }(0);
- }
-
- // src/rewriting/make-home.js
- function addMakeHomeButton() {
- if (document.querySelector(`#` + constants_default.MAKE_HOME_BUTTON_ID))
- return false;
- if (!isRemoteLemmyUrl(location) || location.pathname !== `/settings`)
- return false;
- const insertAfter = document.querySelector(`#user-password`)?.closest(`.card`);
- if (!insertAfter)
- return;
- const button = document.createElement(`button`);
- button.id = constants_default.MAKE_HOME_BUTTON_ID;
- button.setAttribute(`class`, `btn btn-block btn-primary mr-4 w-100`);
- button.innerHTML = `Make this my home instance for URL rewriting`;
- button.addEventListener(`click`, () => {
- setHome(location.origin);
- button.remove();
- });
- registerAddedNode(constants_default.MAKE_HOME_BUTTON_ID, `#` + constants_default.MAKE_HOME_BUTTON_ID);
- insertAfter.insertAdjacentElement("afterend", button);
- return true;
- }
-
- // src/rewriting/show-at-home.js
- function showAtHomeButtonText() {
- const host = new URL(HOME).hostname;
- return `Show on ${host}`;
- }
- function createShowAtHomeAnchor(localUrl) {
- const showAtHome = document.createElement(`a`);
- showAtHome.dataset.creationHref = location.href;
- showAtHome.classList.add(constants_default.SHOW_AT_HOME_BUTTON_CLASS);
- showAtHome.innerHTML = showAtHomeButtonText();
- showAtHome.href = localUrl;
- registerAddedNode(constants_default.SHOW_AT_HOME_BUTTON_CLASS, `.` + constants_default.SHOW_AT_HOME_BUTTON_CLASS);
- return showAtHome;
- }
- function addLemmyShowAtHomeButton(localUrl) {
- const logo = document.querySelector(`a.navbar-brand`);
- const navbarIcons = isV17() ? document.querySelector(`[title="Search"]`)?.closest(`.navbar-nav`) : document.querySelector(`#navbarIcons`);
- if (!logo || !navbarIcons) {
- debug(`Could not find position to insert ShowAtHomeButton at`);
- return false;
- }
- const mobile = createShowAtHomeAnchor(localUrl);
- mobile.classList.add(`d-md-none`);
- mobile.style[`margin-right`] = `8px`;
- mobile.style[`margin-left`] = `auto`;
- if (isV17()) {
- document.querySelector(`.navbar-nav.ml-auto`)?.classList.remove(`ml-auto`);
- }
- logo.insertAdjacentElement("afterend", mobile);
- const desktop = createShowAtHomeAnchor(localUrl);
- desktop.classList.add(`d-md-inline`);
- desktop.style[`margin-right`] = `8px`;
- navbarIcons.insertAdjacentElement("beforebegin", desktop);
- return true;
- }
- function addKbinShowAtHomeButton(localUrl) {
- const prependTo = document.querySelector(`#header menu:not(.head-nav__menu)`);
- if (!prependTo) {
- debug(`Could not find position to insert ShowAtHomeButton at`);
- return false;
- }
- const item = document.createElement(`li`);
- item.append(createShowAtHomeAnchor(localUrl));
- prependTo.prepend(item);
- return true;
- }
- function addButton(localUrl) {
- const oldButton = document.querySelectorAll(`.` + constants_default.SHOW_AT_HOME_BUTTON_CLASS);
- if (oldButton.length > 0 && oldButton[0].dataset.creationHref !== location.href) {
- debug(`Removing old show at home button`);
- oldButton.forEach((btn) => btn.remove());
- } else if (oldButton.length > 0) {
- debug(`Old show at home button still exists`);
- return false;
- }
- if (!localUrl) {
- debug(`No local URL for show at home button found`);
- return false;
- } else if (isRemoteLemmyUrl(location)) {
- return addLemmyShowAtHomeButton(localUrl);
- } else if (isRemoteKbinUrl(location)) {
- return addKbinShowAtHomeButton(localUrl);
- } else {
- return false;
- }
- }
- async function addShowAtHomeButton() {
- if (isInstantlyRewritable(location)) {
- return addButton(findLocalUrl(location));
- } else if (isRewritableAfterResolving(location)) {
- try {
- return addButton(await fetchLocalUrl(location));
- } catch (e) {
- debug(`Error while trying to add "show at home" button`, e);
- }
- }
- }
-
- // src/rewriting/rewrite.js
- function triggerRewrite() {
- doAllDomChanges();
- }
- function isOrHasOurAddedNode(node) {
- return getAddedNodesSelectors().some((selector) => node.matches?.(selector) || node.querySelector?.(selector));
- }
- function isIrrelevantChange(change) {
- if (change.type === `childList`) {
- if (Array.from(change.removedNodes).some(isOrHasOurAddedNode)) {
- trace(`Change`, change, `is relevant because a removed node is/has ours`);
- return false;
- }
- if (!Array.from(change.addedNodes).every(isOrHasOurAddedNode)) {
- trace(`Change`, change, `is relevant because not every added node is/has ours`);
- return false;
- }
- } else if (change.type === `attributes` && isRemoteUrl(new URL(change.target.href))) {
- trace(`Change`, change, `is relevant because href changed to a remote URL`);
- return false;
- }
- trace(`Change`, change, `is irrelevant`);
- return true;
- }
- async function startRewriting() {
- new MutationObserver((changes, observer) => {
- debug(`MutationObserver triggered`, changes);
- if (changes.every(isIrrelevantChange)) {
- debug(`All observed changes are irrelevant`);
- return;
- }
- doAllDomChanges(changes);
- }).observe(document.body, {
- subtree: true,
- childList: true,
- attributeFilter: [`href`]
- });
- await doAllDomChanges();
- }
- async function doAllDomChanges(changes) {
- debug(`doAllDomChanges start`);
- const addedMakeHomeButton = addMakeHomeButton();
- if (addedMakeHomeButton)
- debug(`Added Make Home Button`);
- const addedShowAtHomeButton = HOME ? addShowAtHomeButton() : false;
- if (addedShowAtHomeButton)
- debug(`Added Show At Home Button`);
- const rewrittenLinks = HOME ? await rewriteLinksToLocal(changes) : false;
- if (rewrittenLinks)
- debug(`Rewritten some links`);
- debug(`doAllDomChanges end`);
- }
-
- // src/home.js
- var HOME;
- async function initHome() {
- HOME = await getValue(`home`);
- if (!HOME && isLemmyInstance(location) && confirm(`Lemmy Universal Link Switcher: Set this instance to be your home instance to which all URLs get rewritten to?`)) {
- setHome(location.origin);
- }
- }
- async function setHome(newHome) {
- if (typeof newHome !== `string`) {
- newHome = null;
- }
- HOME = newHome;
- await setValue(`home`, newHome);
- }
- async function getHome() {
- return await getValue(`home`);
- }
- function updateHomePeriodically() {
- debug(`Current HOME`, HOME);
- setInterval(async () => {
- const prev = HOME;
- await setHome(await getHome());
- if (prev !== HOME) {
- debug(`HOME changed from`, prev, `to`, HOME);
- triggerRewrite();
- }
- }, 1337);
- }
-
- // src/main.js
- (async () => {
- await initHome();
- updateHomePeriodically();
- await initAuth();
- updateAuthPeriodically();
- startRewriting();
- })();
- })();