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

'); +});