Several traits of this codebase cost time to rediscover and are invisible in the source: both scripts share a stylesheet namespace on thread pages, the page indicator in the forum markup is split across inline tags so searching the raw HTML for it comes up empty, and anything appended to the body has to come after the original content is hidden. The file also records the throwaway jsdom harness used to check the thread script against a saved page, since the project deliberately carries no test dependencies and the setup is easy to get wrong. Claude-Session: https://claude.ai/code/session_0158owAAsXAfFiT3hGkQt1Xk
iOS Safari Userscripts — cs.rin.ru
English
Two userscripts that rebuild the phpBB2 pages of cs.rin.ru into a mobile card
layout for Safari on iOS. Both replace the original table layout entirely: the
existing page content is hidden and a freshly built DOM is appended to <body>.
| Script | Matches | Purpose |
|---|---|---|
rin-mobile.user.js |
*://cs.rin.ru/forum/* |
Topic lists (viewforum.php, search.php) as cards |
rin-thread.user.js |
*://cs.rin.ru/forum/viewtopic.php* |
Single thread as a post stream with a fixed bottom navigation bar |
The thread navigation bar holds first / previous / next / last and a page
indicator. Tapping the indicator opens a sheet with a number field and a grid of
all pages. Targets are computed as start = (page - 1) × per_page rather than
taken from the rendered page links, because phpBB only ever shows a handful of
them. per_page is read from the jumpto() function the forum embeds in the
page; without it, only first page and the original previous/next links remain
available.
Both scripts run at document-start, inject a mobile viewport meta tag, and
carry a DEBUG flag. While DEBUG is true, a green diagnostic overlay is
prepended to the page showing how many rows were found and converted. Set it to
false in both files before daily use.
Installation on iOS
- Install a userscript manager for Safari on iOS (for example Userscripts) and enable it under Settings → Safari → Extensions.
- Add
rin-mobile.user.jsandrin-thread.user.jsto the manager's script directory. - Grant the extension permission for
cs.rin.ru.
Development
The scripts are developed on Windows in Chrome or Edge with Tampermonkey. The
files in dev/ are loaders: they contain nothing but a metadata block that
pulls in the real script from disk via @require. Editing
rin-mobile.user.js or rin-thread.user.js and reloading the page is enough —
no reinstall in Tampermonkey.
⚠️ Path adjustment required
The loaders in dev/ reference the scripts by absolute path:
// @require file:///C:/Projekte/ios_safari_userscripts/rin-mobile.user.js
This path is hardcoded and only valid on the machine it was written for. After
cloning the repository or moving the project folder, adjust the @require line
in both loaders to your own location:
dev/rin-mobile.dev.user.jsdev/rin-thread.dev.user.js
Use forward slashes and the file:/// prefix, including the drive letter —
file:///D:/projects/ios_safari_userscripts/rin-mobile.user.js. A @require
that cannot be resolved causes Tampermonkey to skip the script entirely and
without an error message on the page, which looks exactly like the script not
being installed at all.
Tampermonkey setup
Three settings are required; missing the first one is the most common cause of "nothing happens":
chrome://extensions→ Tampermonkey → enable Allow user scripts. On older Chrome versions, enable Developer mode at the top right instead. Without this, Manifest V3 blocks all injection.- Same page → enable Allow access to file URLs, so
@require file://can be resolved. - Tampermonkey dashboard → Settings → Externals → set the update interval to always, otherwise the loader keeps serving a cached copy of the script.
Then open the loaders once via file:///.../dev/rin-mobile.dev.user.js —
Tampermonkey intercepts .user.js URLs and offers to install them.
Do not run the loaders and the plain scripts side by side. If both are enabled in Tampermonkey, the code executes twice on the same page, producing duplicate cards and two debug overlays.
Test fixtures
cs.rin.ru requires a login, so save the pages you need once and iterate
against local copies:
- Open the page while logged in, then in DevTools right-click
<html>→ Copy outerHTML. - Save it as
dev/viewtopic.php.htmlordev/viewforum.php.html. - Serve the folder:
python -m http.server 8777 --directory .
The file name matters twice over. The .html extension makes the server send
the file as HTML instead of offering it as a download, and the retained
viewtopic.php / viewforum.php part is what the loaders' @include rules
and the page-type check in rin-mobile.user.js match against.
Forum images and stylesheets are missing from such a snapshot. That is fine for
layout work, because the scripts rebuild the DOM anyway — only avatars stay
empty, since their src is carried over unchanged.
Note that a snapshot saved while logged out contains span.link_removed
placeholders instead of links, and may use different markup for author names
than the logged-in view.
Device emulation
DevTools → Device Toolbar (Ctrl+Shift+M) → Edit… → add a custom device
with 430 × 932 and DPR 3 for an iPhone 15 Pro Max, device type Mobile,
and an iOS Safari user agent string.
What desktop emulation cannot show
Chrome uses Blink, iOS Safari uses WebKit. These points have to be verified on the device:
env(safe-area-inset-bottom)in.rm-nav— always0in the emulator, so the clearance for the home indicator is untested.- A bottom
position: fixedbar together with Safari's collapsing toolbar. width: 100vw— on the desktop the scrollbar counts towards it and creates phantom overflow, so the debug overlay reports different numbers than iOS.-webkit-text-size-adjustand Safari's automatic font scaling.-webkit-backdrop-filterrenders in Chrome, but looks different.
For higher fidelity without an iPhone, Playwright ships a real WebKit build for
Windows (npx playwright install webkit).
Troubleshooting
Install dev/tm-test.user.js — it injects a red bar and nothing else. If the
bar does not appear, the problem is Tampermonkey (see setup above), not the
script code. If it does appear, check the loader's Externals tab in the
Tampermonkey dashboard: an empty or failed entry means the @require path is
wrong.
If Tampermonkey keeps serving a stale copy despite the update interval, replace
the file:// require with a local HTTP server, which does not cache:
// @require http://localhost:8777/rin-mobile.user.js
Repository layout
rin-mobile.user.js topic list → cards
rin-thread.user.js thread → post stream
dev/
rin-mobile.dev.user.js loader, @require with absolute path
rin-thread.dev.user.js loader, @require with absolute path
Deutsch
Zwei Userscripts, die die phpBB2-Seiten von cs.rin.ru für Safari auf iOS in
eine mobile Kartenansicht umbauen. Beide ersetzen das ursprüngliche
Tabellenlayout vollständig: der vorhandene Seiteninhalt wird ausgeblendet und
ein neu gebautes DOM an <body> gehängt.
| Script | Greift auf | Zweck |
|---|---|---|
rin-mobile.user.js |
*://cs.rin.ru/forum/* |
Themenlisten (viewforum.php, search.php) als Karten |
rin-thread.user.js |
*://cs.rin.ru/forum/viewtopic.php* |
Einzelner Thread als Beitragsstrom mit fixierter Navigationsleiste |
Die Navigationsleiste im Thread enthält erste / vorherige / nächste / letzte
Seite und eine Positionsanzeige. Ein Tipp darauf öffnet ein Sheet mit
Zahlenfeld und einem Raster aller Seiten. Die Ziele werden als
start = (Seite - 1) × per_page berechnet und nicht aus den gerenderten
Seitenlinks übernommen, weil phpBB davon immer nur eine Handvoll anzeigt.
per_page stammt aus der jumpto()-Funktion, die das Forum in die Seite
einbettet; fehlt sie, bleiben nur die erste Seite und die ursprünglichen
Zurück-/Weiter-Links nutzbar.
Beide laufen bei document-start, setzen ein mobiles Viewport-Meta-Tag und
haben ein DEBUG-Flag. Solange DEBUG auf true steht, wird ein grünes
Diagnose-Overlay über die Seite gelegt, das zeigt, wie viele Zeilen gefunden und
umgewandelt wurden. Für den täglichen Gebrauch in beiden Dateien auf false
setzen.
Installation unter iOS
- Einen Userscript-Manager für Safari unter iOS installieren (zum Beispiel Userscripts) und unter Einstellungen → Safari → Erweiterungen aktivieren.
rin-mobile.user.jsundrin-thread.user.jsin das Script-Verzeichnis des Managers legen.- Der Erweiterung die Berechtigung für
cs.rin.ruerteilen.
Entwicklung
Entwickelt wird unter Windows in Chrome oder Edge mit Tampermonkey. Die Dateien
in dev/ sind Loader: sie enthalten nur einen Metadatenblock, der das
eigentliche Script per @require von der Platte einbindet. Es genügt,
rin-mobile.user.js oder rin-thread.user.js zu bearbeiten und die Seite neu
zu laden — keine Neuinstallation in Tampermonkey nötig.
⚠️ Pfadanpassung erforderlich
Die Loader in dev/ verweisen mit einem absoluten Pfad auf die Scripts:
// @require file:///C:/Projekte/ios_safari_userscripts/rin-mobile.user.js
Dieser Pfad ist fest eingetragen und gilt nur auf dem Rechner, für den er
geschrieben wurde. Nach dem Klonen des Repositories oder dem Verschieben des
Projektordners muss die @require-Zeile in beiden Loadern auf den eigenen
Ablageort angepasst werden:
dev/rin-mobile.dev.user.jsdev/rin-thread.dev.user.js
Dabei Schrägstriche und das Präfix file:/// inklusive Laufwerksbuchstaben
verwenden — file:///D:/projekte/ios_safari_userscripts/rin-mobile.user.js.
Ein @require, das nicht aufgelöst werden kann, führt dazu, dass Tampermonkey
das Script komplett und ohne Fehlermeldung auf der Seite überspringt. Das
sieht exakt so aus, als wäre gar kein Script installiert.
Tampermonkey einrichten
Drei Einstellungen sind nötig; die erste ist die mit Abstand häufigste Ursache für „es passiert überhaupt nichts":
chrome://extensions→ Tampermonkey → Nutzerskripte zulassen aktivieren. Bei älteren Chrome-Versionen stattdessen den Entwicklermodus oben rechts einschalten. Ohne das blockiert Manifest V3 jede Injektion.- Auf derselben Seite → Zugriff auf Datei-URLs zulassen aktivieren, damit
@require file://aufgelöst werden kann. - Tampermonkey-Dashboard → Einstellungen → Externals → Update-Intervall auf immer stellen, sonst liefert der Loader weiterhin eine zwischen gespeicherte Fassung des Scripts aus.
Danach die Loader einmal über file:///.../dev/rin-mobile.dev.user.js öffnen —
Tampermonkey fängt .user.js-URLs ab und bietet die Installation an.
Die Loader nicht parallel zu den unveränderten Scripts betreiben. Sind beide in Tampermonkey aktiv, läuft der Code doppelt auf derselben Seite, mit doppelten Karten und zwei Debug-Overlays als Folge.
Geräte-Emulation
DevTools → Device Toolbar (Strg+Umschalt+M) → Edit… → eigenes Gerät mit
430 × 932 und DPR 3 für ein iPhone 15 Pro Max anlegen, Gerätetyp
Mobile, dazu einen iOS-Safari-User-Agent eintragen.
Was die Desktop-Emulation nicht zeigt
Chrome verwendet Blink, iOS Safari verwendet WebKit. Diese Punkte müssen am Gerät geprüft werden:
env(safe-area-inset-bottom)in.rm-nav— im Emulator immer0, die Freihaltung für den Home-Indicator bleibt also ungetestet.- Eine unten fixierte Leiste zusammen mit Safaris ein- und ausfahrender Toolbar.
width: 100vw— auf dem Desktop zählt die Scrollbar mit und erzeugt Phantom-Overflow, das Debug-Overlay meldet dort andere Zahlen als unter iOS.-webkit-text-size-adjustund Safaris automatische Schriftvergrößerung.-webkit-backdrop-filterrendert in Chrome, sieht aber anders aus.
Für höhere Treue ohne iPhone bringt Playwright einen echten WebKit-Build für
Windows mit (npx playwright install webkit).
Fehlersuche
dev/tm-test.user.js installieren — das Script blendet nur einen roten Balken
ein, sonst nichts. Erscheint der Balken nicht, liegt das Problem bei
Tampermonkey (siehe Einrichtung oben) und nicht am Script-Code. Erscheint er,
im Tampermonkey-Dashboard den Tab Externals des Loaders prüfen: ein leerer
oder fehlgeschlagener Eintrag bedeutet, dass der @require-Pfad falsch ist.
Liefert Tampermonkey trotz Update-Intervall weiterhin einen veralteten Stand
aus, das file://-Require durch einen lokalen HTTP-Server ersetzen, der nicht
zwischenspeichert:
// @require http://localhost:8777/rin-mobile.user.js
Aufbau des Repositories
rin-mobile.user.js Themenliste → Karten
rin-thread.user.js Thread → Beitragsstrom
dev/
rin-mobile.dev.user.js Loader, @require mit absolutem Pfad
rin-thread.dev.user.js Loader, @require mit absolutem Pfad