Show a picture whose address was typed without a scheme
CI / Typecheck, test, build (pull_request) Successful in 26s
CI / Typecheck, test, build (pull_request) Successful in 26s
`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 <[email protected]> Claude-Session: https://claude.ai/code/session_017nMQ2eDKnqALYhAibpTKTu
This commit is contained in:
+13
-3
@@ -69,7 +69,12 @@ const INLINE = new RegExp(
|
||||
'(?<![\\w*])\\*([^*\\n]+)\\*(?![\\w*])', // 8 em with asterisks
|
||||
'(?<![\\w_])_([^_\\n]+)_(?![\\w_])', // 9 em with underscores
|
||||
'(https?://[^\\s<>]+)', // 10 bare url
|
||||
'(?<![\\w/])(/?[ru]/[A-Za-z0-9_][A-Za-z0-9_-]{1,30})', // 11 r/sub and u/name
|
||||
// 11 the same thing with the scheme left off, which is how people type
|
||||
// them. Narrow on purpose: a host, a path, and an image extension. Prose
|
||||
// is full of dotted words, and `src/render/post.ts` must not become a
|
||||
// link to a website in Tonga.
|
||||
'(?<![\\w@/.])((?:[a-z0-9-]+\\.)+[a-z]{2,}/[^\\s<>]*\\.(?:jpe?g|png|gif|webp|avif)(?:\\?[^\\s<>]*)?)',
|
||||
'(?<![\\w/])(/?[ru]/[A-Za-z0-9_][A-Za-z0-9_-]{1,30})', // 12 r/sub and u/name
|
||||
].join('|'),
|
||||
'g',
|
||||
);
|
||||
@@ -80,8 +85,8 @@ function inline(text: string, image?: ImageRenderer): string {
|
||||
let cursor = 0;
|
||||
|
||||
for (const match of text.matchAll(INLINE)) {
|
||||
const [whole, code, alt, src, label, href, strong, strike, emStar, emScore, url, subOrUser] =
|
||||
match;
|
||||
const [whole, code, alt, src, label, href, strong, strike, emStar, emScore, url, schemeless,
|
||||
subOrUser] = match;
|
||||
out += escapeHtml(text.slice(cursor, match.index));
|
||||
cursor = match.index + whole.length;
|
||||
|
||||
@@ -113,6 +118,11 @@ function inline(text: string, image?: ImageRenderer): string {
|
||||
} else {
|
||||
out += anchor(safe, trimmed.replace(/^https?:\/\/(www\.)?/, '')) + tail;
|
||||
}
|
||||
} else if (schemeless !== undefined) {
|
||||
// Assumed https: every host that serves these redirects to it anyway,
|
||||
// and a picture is the one thing worth guessing a scheme for.
|
||||
const safe = safeHref(`https://${schemeless}`);
|
||||
out += safe ? (image ? image(safe, '') : anchor(safe, schemeless)) : escapeHtml(whole);
|
||||
} else if (subOrUser !== undefined) {
|
||||
const path = subOrUser.startsWith('/') ? subOrUser : `/${subOrUser}`;
|
||||
out += anchor(`${REDDIT}${path}`, subOrUser);
|
||||
|
||||
Reference in New Issue
Block a user