Add Links list mode with URL previews and tweet embeds#26
Add Links list mode with URL previews and tweet embeds#26bclinkinbeard wants to merge 2 commits intomainfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5297701376
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const isTextMode = currentEntryMode === 'text'; | ||
| const currentMode = listDetailMode ? listDetailMode.dataset.mode : ''; | ||
| const isLinks = currentMode === 'links'; | ||
| if (hasList && isLinks && !isTextMode) { | ||
| currentEntryMode = 'text'; |
There was a problem hiding this comment.
Recompute isTextMode after forcing Links mode
updateEntryModeUi calculates isTextMode before it forces currentEntryMode = 'text' for Links lists, so the rest of the function still behaves as if voice mode is active. When a user opens a Links list while currently in voice mode, the text entry panel is hidden (and the mode toggle is also hidden for Links), leaving no way to add a link until another UI refresh occurs.
Useful? React with 👍 / 👎.
| accomplish: 'Track tasks with checkboxes and reordering.', | ||
| links: 'Save URLs and preview each link as a card.' |
There was a problem hiding this comment.
Preserve links mode across sync snapshots
This change introduces a new links mode in the client, but sync sanitization still collapses any non-accomplish mode to capture (sync-snapshot.js, sanitizeListRecord). As soon as a Links list is pushed to cloud, its mode is rewritten to capture and other devices (or restored data) lose Links behavior, which is a data-corrupting regression for synced users.
Useful? React with 👍 / 👎.
| if (!/^https?:$/i.test(parsed.protocol)) { | ||
| return jsonResponse({ ok: false, error: 'Only HTTP(S) URLs are supported.' }, { status: 400 }); | ||
| } | ||
|
|
||
| const html = await fetchHtml(parsed.toString()); |
There was a problem hiding this comment.
Block internal-network SSRF targets in preview API
The new /api/link-preview route performs server-side fetches for any user-provided HTTP(S) URL, but only validates the scheme. In environments where the function can reach internal addresses, this enables SSRF against loopback/link-local/private hosts (for example metadata endpoints), so host/IP range checks are needed before issuing the fetch.
Useful? React with 👍 / 👎.
| const text = await response.text(); | ||
| return text.slice(0, MAX_HTML_LENGTH); |
There was a problem hiding this comment.
Enforce HTML size limit before reading full response
fetchHtml calls response.text() and only then truncates to MAX_HTML_LENGTH, so the configured cap does not prevent large upstream payloads from being fully downloaded and buffered. A large response can still cause avoidable memory/CPU pressure before truncation is applied.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 47b3d40209
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (markdownMatch && markdownMatch[1]) { | ||
| return markdownMatch[1]; | ||
| } | ||
| const directMatch = normalized.match(/https?:\/\/[^\s<>"')]+/i); |
There was a problem hiding this comment.
Allow URLs that contain closing parentheses
The URL extraction regex excludes ) from the matched URL, so valid links like https://en.wikipedia.org/wiki/Taylor_(Swift_album) are truncated before saving. In Links mode this stores a broken URL (missing the closing parenthesis), which then causes incorrect previews and wrong outbound links for any URL with parenthetical path segments.
Useful? React with 👍 / 👎.
| .catch(() => readPersistedPreview(url)); | ||
|
|
||
| linkPreviewCache.set(url, request); |
There was a problem hiding this comment.
Retry preview fetches after transient failures
Failed preview requests are cached as a resolved null promise via .catch(() => readPersistedPreview(url)) and then linkPreviewCache.set(url, request), so a temporary network/API failure permanently suppresses retries for that URL until a full page reload. This makes previews stay unavailable for the rest of the session even after connectivity recovers.
Useful? React with 👍 / 👎.
Motivation
Description
linksmode to the UI and mode selector and surface it inMODE_DESCRIPTIONS, the modal, list badges, and help copy (app.js,index.html).app.jsadditions:normalizeLinkInput,isTweetUrl,populateLinkPreview,fetchLinkPreviewusage, and recording guard for Links lists).GET /api/link-previewthat fetches upstream HTML with timeout/length limits and extractsog:*, twitter meta tags and<title>to return a safe preview JSON (api/link-preview.js).app.css).Testing
node --check app.js, which completed successfully.npm test(which executesnode tests.jsand node --test on unit tests), and all tests passed (297/297tests passed).Codex Task