From e64e83c1244bb1d20fb4b6a3763bb375e53b8e5f Mon Sep 17 00:00:00 2001 From: James Griffin Date: Thu, 27 Aug 2026 13:23:47 -0300 Subject: [PATCH] Make the rewrite rules copyable from the file, not just the render The rules were a Markdown table, and a table cell cannot hold a bare `|`. It has to be written `\|`, which renders as a pipe and copies as a backslash and a pipe. Every one of these rules is an alternation full of pipes, so anyone reading README.md rather than a rendered view -- which, for a self-hosted thing, is most of the time -- got a regex whose alternation had quietly become literal characters. It matches nothing, and nothing about it looks wrong. That is not hypothetical: it is how this came up. The Reddit rule is the longest row, and reading it out of the file gave something that plainly did not work, so the backslashes came out. Which fixed the copy and broke the table -- four pipes turned into column separators, the row became seven cells, the separator row was widened to seven to match, and `(.*)` picked up an escape on the way past. Restoring the row would have left the trap exactly where it was, for the next person or the same one. So the table is now a code block: each rule is a comment naming the platform, then the find field, then the replace field, one per line. Nothing is escaped, the file and the render agree, and each field is a whole line to select. Every rule is checked by reading the block out of README.md byte for byte with no unescaping step -- the copy-paste path -- compiling it, and running it: all seven, against nineteen URLs including mobile.x.com, threads.net, the TikTok vm. and vt. hosts, five Reddit subdomains, a /s/ share link and a redd.it short code. Also reformats the rest of the file, and stops calling it a table on the way past. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_017nMQ2eDKnqALYhAibpTKTu --- README.md | 65 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 69450f7..4bdcf9c 100644 --- a/README.md +++ b/README.md @@ -21,15 +21,43 @@ readable in your history. Replace `antisocial.example.com` with wherever you are running it. -| Platform | Find | Replace | -| --------- | ------------------------------------------------------------- | ------------------------------------------- | -| X | `/^https:\/\/(?:www\.\|mobile\.)?(?:x\|twitter)\.com\/(.*)$/` | `https://antisocial.example.com/x/$1` | -| Threads | `/^https:\/\/(?:www\.)?threads\.(?:net\|com)\/(.*)$/` | `https://antisocial.example.com/threads/$1` | -| Instagram | `/^https:\/\/(?:www\.)?instagram\.com\/(.*)$/` | `https://antisocial.example.com/ig/$1` | -| TikTok | `/^https:\/\/(?:www\.\|vm\.\|vt\.)?tiktok\.com\/(.*)$/` | `https://antisocial.example.com/tiktok/$1` | -| Bluesky | `/^https:\/\/bsky\.app\/(.*)$/` | `https://antisocial.example.com/bsky/$1` | -| Reddit | `/^https:\/\/(?:www\.\|old\.\|new\.\|np\.\|m\.)?reddit\.com\/(.*)$/` | `https://antisocial.example.com/reddit/$1` | -| Reddit | `/^https:\/\/redd\.it\/(.*)$/` | `https://antisocial.example.com/reddit/$1` | +Each rule is two fields. Both are on their own line below, and neither needs any +escaping — copy them straight out of this file. + +```text +# X +/^https:\/\/(?:www\.|mobile\.)?(?:x|twitter)\.com\/(.*)$/ +https://antisocial.example.com/x/$1 + +# Threads +/^https:\/\/(?:www\.)?threads\.(?:net|com)\/(.*)$/ +https://antisocial.example.com/threads/$1 + +# Instagram +/^https:\/\/(?:www\.)?instagram\.com\/(.*)$/ +https://antisocial.example.com/ig/$1 + +# TikTok +/^https:\/\/(?:www\.|vm\.|vt\.)?tiktok\.com\/(.*)$/ +https://antisocial.example.com/tiktok/$1 + +# Bluesky +/^https:\/\/bsky\.app\/(.*)$/ +https://antisocial.example.com/bsky/$1 + +# Reddit +/^https:\/\/(?:www\.|old\.|new\.|np\.|m\.)?reddit\.com\/(.*)$/ +https://antisocial.example.com/reddit/$1 + +# Reddit short links +/^https:\/\/redd\.it\/(.*)$/ +https://antisocial.example.com/reddit/$1 +``` + +A code block rather than a table, because a table cell cannot hold a bare `|` — it has +to be written `\|`, which renders correctly and copies wrongly. The alternation in these +rules is full of them, and a regex whose pipes arrive as literal pipes matches nothing +and says nothing about why. So `https://x.com/user/status/123` becomes `https://antisocial.example.com/x/user/status/123`. @@ -42,7 +70,8 @@ where it came from Reddit. A Reddit `/r//s/` share link is followed t post it points at, and that permalink — not the opaque share code — is what the copy button hands back. -`/` serves this table with the live hostnames, if you'd rather read it there. +`/` serves these rules with the live hostname already filled in, if you'd rather copy +them from there. ## How it works @@ -59,13 +88,13 @@ Each adapter layers its extraction, most structured first: 3. **The rendered DOM** — whatever is actually on screen is real. 4. **Open Graph tags** — the floor, and enough to show something. -| Platform | Loads | Reads | -| --------- | ---------------------------- | -------------------------------------------------------- | -| Bluesky | the public AT Protocol API | `getPostThread`; falls back to the post page | -| X | `platform.twitter.com` embed | the `cdn.syndication.twimg.com/tweet-result` response | -| Instagram | `/embed/captioned/` | `shortcode_media`, then the rendered `