Make paywalls systemic + fix ArticleCard reactivity

- ArticleCard: derive safeHref from article.url and reset image-failure state
  when the article changes, so in-place replacements re-evaluate correctly
  (clears the Svelte capture warning; build is warning-free again).
- Downweight paywalled stories below readable ones (stable sort) when composing
  the daily five and in feed results — the brief now leads readable and rarely
  hands over a locked door.
- review_sources gains a 'paywall-heavy' advisory flag (Nature, New Scientist
  flag at 100%); never auto-deactivates.
- New Scientist/Nature kept active but no longer reach the daily five; they
  remain browsable with the label + Replace.
- Tests: brief readability preference + paywall-heavy flag (79 total).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
jay
2026-05-31 01:36:53 +00:00
parent bfd612eb9b
commit ba801d90f6
7 changed files with 89 additions and 8 deletions
+12 -6
View File
@@ -1,11 +1,17 @@
<script>
let { article, onaction, onreplace, hero = false } = $props();
let imgOk = $state(!!article.image_url);
let hasImg = $derived(!!(article.image_url && imgOk));
const safeHref =
typeof article.url === 'string' && /^https?:\/\//.test(article.url) ? article.url : '#';
// Cards can be replaced in place, so derive from the current article prop and
// reset the image-failure flag whenever the image URL changes.
let failed = $state(false);
$effect(() => {
void article.image_url;
failed = false;
});
let hasImg = $derived(!!article.image_url && !failed);
let safeHref = $derived(
typeof article.url === 'string' && /^https?:\/\//.test(article.url) ? article.url : '#'
);
function act(kind, value) {
if (value) onaction?.(kind, value);
@@ -24,7 +30,7 @@
{#if hasImg}
<a class="media" href={safeHref} target="_blank" rel="noopener">
<img src={article.image_url} alt="" loading="lazy" referrerpolicy="no-referrer"
onerror={() => (imgOk = false)} />
onerror={() => (failed = true)} />
</a>
{/if}