From 031101c382b8a05575cf0ab66dc8764d43301c46 Mon Sep 17 00:00:00 2001 From: James Griffin Date: Thu, 27 Aug 2026 16:19:25 -0300 Subject: [PATCH] Show a picture whose address was typed without a scheme `preview.redd.it/lz4drsqh0clh1.jpeg?width=1290&...` was rendering as plain text -- not a picture, and not even a link. The bare-address rule has always insisted on `https://`, so anything copied out of an address bar, where the browser hides the scheme, fell through to nothing at all. That predates the inline images from the last commit; it just did not matter until pictures started being worth placing. The rule is deliberately narrow: a host with a dot, a path, and an image extension. Widening it to every schemeless address would be the obvious move and is wrong, because a comment thread is full of dotted, slashed prose -- `src/render/post.ts` would become a link to a website in Tonga, and `node_modules/foo/bar.js` a website in Jersey. Requiring the extension costs nothing here, since the only thing worth guessing a scheme for is a picture. https is assumed. Every host that serves these redirects to it anyway. Checked both ways: the four address shapes that should become pictures do, and nine pieces of ordinary prose that must not -- file paths, a Windows drive letter, a relative path, an email address followed by a filename, a version number -- still do not. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_017nMQ2eDKnqALYhAibpTKTu --- CLAUDE.md | 5 ++++- src/render/markdown.ts | 16 +++++++++++++--- test/markdown.test.ts | 31 +++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 2366241..da93618 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -153,7 +153,10 @@ Things worth knowing before editing: a key in that same comment's own `media_metadata`, so `resolveInlineImages` is one lookup rather than three special cases. A bare `preview.redd.it` address pasted into a comment is in there too, keyed by the id inside the URL. Prefer `s.gif` over `s.mp4` - for an animated one: a GIF moves in an `` and an MP4 needs a player. + for an animated one: a GIF moves in an `` and an MP4 needs a player. An address + typed without a scheme counts as well, but only when it ends in an image extension — + the rule wants a host, a path *and* that extension, because comments are full of + dotted, slashed prose that must not turn into links. - **Threads** — same media schema as Instagram (`src/platforms/meta-media.ts`). Its payloads are full of empty stub nodes, so the finder only accepts a node with actual candidates in it. The page ships the linked post, the author's follow-ups, other diff --git a/src/render/markdown.ts b/src/render/markdown.ts index 4f519e4..cd1c0c4 100644 --- a/src/render/markdown.ts +++ b/src/render/markdown.ts @@ -69,7 +69,12 @@ const INLINE = new RegExp( '(?]+)', // 10 bare url - '(?]*\\.(?:jpe?g|png|gif|webp|avif)(?:\\?[^\\s<>]*)?)', + '(? test('images inside a quote are still placed', () => { assert.match(mdi('> ![](https://i.redd.it/x.gif)'), /

{ + // Which is how people type them: no https, straight from the address bar. + const out = mdi('preview.redd.it/lz4drsqh0clh1.jpeg?width=1290&s=b27e'); + assert.ok(out.includes(' { + const out = mdi('look at i.redd.it/x.png nice one'); + assert.ok(out.startsWith('

look at '), out); +}); + +test('prose full of dots and slashes is not mistaken for an address', () => { + // The reason this rule insists on a host, a path and an image extension. + for (const text of [ + 'the file is at src/render/post.ts', + 'see node_modules/foo/bar.js', + 'a path like ./images/cat.jpg', + 'C:/Users/x/cat.png', + 'email someone@example.com/nope.jpg', + 'version 1.2.3/4.png', + ]) { + assert.ok(!mdi(text).includes(' { + // Guessing a scheme is worth it for a picture and not for prose. + assert.equal(mdi('example.com/article'), '

example.com/article

'); +});