Files
rin-mobile-userscript/CLAUDE.md
T
Andre c3f56b673d docs: add project instructions for Claude Code
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
2026-08-02 14:08:59 +02:00

5.1 KiB

CLAUDE.md

Zwei eigenstaendige Userscripts, die die phpBB-Seiten von cs.rin.ru fuer Safari auf iOS in eine mobile Ansicht umbauen. Kein Build, keine Abhaengigkeiten, kein package.json — die .user.js-Dateien sind das Produkt.

Datei Greift auf Zweck
rin-mobile.user.js *://cs.rin.ru/forum/* Themenlisten als Karten
rin-thread.user.js *://cs.rin.ru/forum/viewtopic.php* Thread als Beitragsstrom + Navigationsleiste
dev/*.dev.user.js zusaetzlich localhost:* Loader, binden per @require file:/// die echten Scripts ein
dev/viewtopic.php — Fixture: gespeicherter Thread, 1114 Seiten

Gemeinsames Muster beider Scripts

Beide sind nach demselben Schema gebaut, Aenderungen am einen sind oft auch am anderen faellig:

  1. IIFE mit 'use strict', DEBUG-Flag und log-Array ganz oben
  2. Viewport-Meta setzen (idempotent ueber [data-rm])
  3. Kompletter Style-Block als Template-Literal, bedingungslos injiziert
  4. build() liest das Original-DOM, baut ein neues div.rm-root
  5. Alle bisherigen body-Kinder bekommen .rm-hidden, dann wird root angehaengt
  6. run() haengt bei DEBUG das gruene Overlay oben an
  7. Start ueber DOMContentLoaded, falls readyState === 'loading'

Fallen, die nicht aus dem Code hervorgehen

Beide Stylesheets sind auf Threadseiten gleichzeitig aktiv. rin-mobile matcht *://cs.rin.ru/forum/*, also auch viewtopic.php. Sein build() steigt dort zwar aus, der Style-Block wird aber vorher injiziert. Gleich benannte Klassen kollidieren mit identischer Spezifitaet, entschieden wird nach Ladereihenfolge der Userscripts — und die ist nicht garantiert.

  • Nur bewusst geteilt: .rm-root, .rm-hidden, .rm-dbg
  • Offene Kollision: .rm-root hat in rin-mobile padding:0 !important, in rin-thread padding:0 0 64px 0 !important. Laedt rin-mobile spaeter, faellt die Freihaltung hinter der fixierten Leiste weg. Noch nicht behoben.
  • Neue Klassen im Thread-Script gegen rin-mobile.user.js gegenpruefen. .rm-goto und .rm-grid heissen genau deshalb so — .rm-jump und .rm-pages waren dort schon belegt.

Was nach body soll, muss nach der Ausblend-Schleife angehaengt werden. Die Schleife markiert alle vorhandenen body-Kinder mit .rm-hidden. Das Sheet im Thread-Script wird deshalb erst beim ersten Antippen gebaut — das loest das Problem nebenbei mit.

Page X of Y steht als Page <strong>1</strong> of <strong>1114</strong> im Markup. Ein Grep im Roh-HTML nach Page 1 of findet nichts, die Regex auf txt(document.body) greift trotzdem. Nicht vorschnell fuer kaputt halten.

per_page kommt aus der jumpto()-Funktion der Seite (var per_page = '15';). Nur damit lassen sich Seiten-URLs als start = (Seite - 1) * per_page selbst bauen. Die gerenderten Seitenlinks taugen nicht als Quelle — phpBB zeigt bei 1114 Seiten nur 1, 2, 3, 4, 5 … 1114. Ohne per_page degradiert die Leiste auf erste Seite plus die Original-Zurueck/Weiter-Links, das Sheet verschwindet.

postRow() steigt bewusst mehrere tr hoch. Der Beitragstext liegt in einer verschachtelten Tabelle, closest('tr') trifft die innere Zeile ohne Autor- und Profilspalte.

DEBUG steht in beiden Dateien auf true und muss vor dem Ausliefern in beiden auf false. Die Versionsnummer steht ebenfalls doppelt: im @version-Header und im Text des Debug-Overlays.

Testen

Es gibt keine Testsuite. Bewaehrt hat sich ein Wegwerf-Harness mit jsdom im Scratchpad (nicht im Repo ablegen — das Projekt soll abhaengigkeitsfrei bleiben):

const dom = new JSDOM(html, { url: 'https://cs.rin.ru/forum/viewtopic.php?f=10&t=68689&start=45' });

Drei Stolpersteine dabei:

  • JSDOM parst asynchron fertig. Nach eval(src) rund 60 ms warten, sonst hat das Script noch auf DOMContentLoaded gewartet und nichts gebaut.
  • location.href ist in JSDOM nicht ueberschreibbar. Fuer Navigationstests im eingelesenen Quelltext location.href = u; durch einen Hook ersetzen.
  • requestAnimationFrame und scrollIntoView fehlen und muessen gestubbt werden.

Sinnvolle Faelle: erste Seite, zweite Seite, Mitte, letzte Seite, dazu die Degradation ohne per_page und ein Thread ohne Paginierung. Fixture-Eckdaten: f=10&t=68689, per_page = 15, 1114 Seiten, letzte Seite start=16695.

Am Geraet zu pruefen bleibt, was Blink nicht zeigt: env(safe-area-inset-*), fixierte Leisten gegen Safaris ein- und ausfahrende Toolbar, -webkit-backdrop-filter, Schriftskalierung. Details und die Tampermonkey-Einrichtung stehen in der README.

Konventionen

  • ES5-Stil im Script-Code: var, function, keine Arrow Functions, kein let/const. Template-Literals und Set sind in Gebrauch. Keine Transpilation, kein Linter.
  • Kommentare deutsch, Umlaute als ae/oe/ue transliteriert. Echte Umlaute nur in Strings und Regexes, die im UI landen.
  • Kommentare begruenden, warum etwas so gebaut ist (welche DOM-Eigenheit von phpBB dahintersteckt), nicht was der Code tut.
  • CSS-Klassen durchgaengig mit rm- praefixiert.
  • Neue nutzersichtbare Funktionen in der README dokumentieren — zweisprachig, siehe globale Anweisung.