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 <[email protected]> Claude-Session: https://claude.ai/code/session_017nMQ2eDKnqALYhAibpTKTu
This commit is contained in:
@@ -21,15 +21,43 @@ readable in your history.
|
|||||||
|
|
||||||
Replace `antisocial.example.com` with wherever you are running it.
|
Replace `antisocial.example.com` with wherever you are running it.
|
||||||
|
|
||||||
| Platform | Find | Replace |
|
Each rule is two fields. Both are on their own line below, and neither needs any
|
||||||
| --------- | ------------------------------------------------------------- | ------------------------------------------- |
|
escaping — copy them straight out of this file.
|
||||||
| 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` |
|
```text
|
||||||
| Instagram | `/^https:\/\/(?:www\.)?instagram\.com\/(.*)$/` | `https://antisocial.example.com/ig/$1` |
|
# X
|
||||||
| TikTok | `/^https:\/\/(?:www\.\|vm\.\|vt\.)?tiktok\.com\/(.*)$/` | `https://antisocial.example.com/tiktok/$1` |
|
/^https:\/\/(?:www\.|mobile\.)?(?:x|twitter)\.com\/(.*)$/
|
||||||
| Bluesky | `/^https:\/\/bsky\.app\/(.*)$/` | `https://antisocial.example.com/bsky/$1` |
|
https://antisocial.example.com/x/$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` |
|
# 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
|
So `https://x.com/user/status/123` becomes
|
||||||
`https://antisocial.example.com/x/user/status/123`.
|
`https://antisocial.example.com/x/user/status/123`.
|
||||||
@@ -42,7 +70,8 @@ where it came from Reddit. A Reddit `/r/<sub>/s/<code>` share link is followed t
|
|||||||
post it points at, and that permalink — not the opaque share code — is what the copy
|
post it points at, and that permalink — not the opaque share code — is what the copy
|
||||||
button hands back.
|
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
|
## 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.
|
3. **The rendered DOM** — whatever is actually on screen is real.
|
||||||
4. **Open Graph tags** — the floor, and enough to show something.
|
4. **Open Graph tags** — the floor, and enough to show something.
|
||||||
|
|
||||||
| Platform | Loads | Reads |
|
| Platform | Loads | Reads |
|
||||||
| --------- | ---------------------------- | -------------------------------------------------------- |
|
| --------- | ---------------------------- | --------------------------------------------------------------- |
|
||||||
| Bluesky | the public AT Protocol API | `getPostThread`; falls back to the post page |
|
| 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 |
|
| X | `platform.twitter.com` embed | the `cdn.syndication.twimg.com/tweet-result` response |
|
||||||
| Instagram | `/embed/captioned/` | `shortcode_media`, then the rendered `<video>`/`<img>` |
|
| Instagram | `/embed/captioned/` | `shortcode_media`, then the rendered `<video>`/`<img>` |
|
||||||
| TikTok | the post page | `__UNIVERSAL_DATA_FOR_REHYDRATION__` |
|
| TikTok | the post page | `__UNIVERSAL_DATA_FOR_REHYDRATION__` |
|
||||||
| Threads | the post page | the Relay payloads in `<script type="application/json">` |
|
| Threads | the post page | the Relay payloads in `<script type="application/json">` |
|
||||||
| Reddit | the post's own `.json` | the post and the first page of comments; falls back to the page |
|
| Reddit | the post's own `.json` | the post and the first page of comments; falls back to the page |
|
||||||
|
|
||||||
On Bluesky and Threads people write in chains, so where the linked post is part
|
On Bluesky and Threads people write in chains, so where the linked post is part
|
||||||
@@ -93,7 +122,7 @@ Reddit posts come with it: every comment the first page carried, nested the way
|
|||||||
written. Each comment is a `<details>` element, so folding one takes its whole subtree
|
written. Each comment is a `<details>` element, so folding one takes its whole subtree
|
||||||
with it, works without JavaScript and works from the keyboard; a collapsed comment says
|
with it, works without JavaScript and works from the keyboard; a collapsed comment says
|
||||||
how many replies it is hiding. "Collapse all" is the one piece that needs the script,
|
how many replies it is hiding. "Collapse all" is the one piece that needs the script,
|
||||||
which is why it only appears once the script has run. What was behind a *load more* is
|
which is why it only appears once the script has run. What was behind a _load more_ is
|
||||||
not fetched — that is a second page and often a third — but it is counted and said out
|
not fetched — that is a second page and often a third — but it is counted and said out
|
||||||
loud rather than quietly dropped.
|
loud rather than quietly dropped.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user