diff --git a/src/components/ReferralBlock/ReferralBlock.svelte b/src/components/ReferralBlock/ReferralBlock.svelte index 21ad19d5..a2036f80 100644 --- a/src/components/ReferralBlock/ReferralBlock.svelte +++ b/src/components/ReferralBlock/ReferralBlock.svelte @@ -49,13 +49,16 @@ import { onMount } from 'svelte'; import { getTime } from '../SiteHeader/NavBar/NavDropdown/StoryCard/time'; + import type { Referrals } from './types'; + import { articleIsNotCurrentPage } from './filterCurrentPage'; + import type { Article } from './types'; let clientWidth: number; const SECTION_API = 'recent-stories-by-sections-v1'; const COLLECTION_API = 'articles-by-collection-alias-or-id-v1'; - let referrals = []; + let referrals: Article[] = []; const getReferrals = async () => { const isCollection = Boolean(collection); @@ -72,11 +75,12 @@ }), }) ); - const data = await response.json(); + const data = (await response.json()) as Referrals; const articles = data.result.articles .filter((a) => a?.headline_category || a?.kicker?.name) .filter((a) => a?.thumbnail?.renditions?.landscape?.['240w']) .filter((a) => !a?.content?.third_party) + .filter(articleIsNotCurrentPage) .slice(0, number); referrals = articles; } catch { diff --git a/src/components/ReferralBlock/filterCurrentPage.ts b/src/components/ReferralBlock/filterCurrentPage.ts new file mode 100644 index 00000000..03de0e24 --- /dev/null +++ b/src/components/ReferralBlock/filterCurrentPage.ts @@ -0,0 +1,32 @@ +import type { Article } from './types'; + +const getUrlFromPath = (path: string) => { + const base = 'https://www.reuters.com'; + + try { + return new URL(path); + } catch { + try { + return new URL(path, base); + } catch { + return null; + } + } +}; + +const isCurrentPage = (urlPath: string) => { + if (typeof window === 'undefined' || typeof window.location === 'undefined') { + return false; + } + const url = getUrlFromPath(urlPath); + if (!url) return false; + return window.location.href === url.href; +}; + +export const articleIsNotCurrentPage = (article: Article) => { + const { redirect_url: redirectUrl, canonical_url: canonicalUrl } = article; + + if (redirectUrl) return !isCurrentPage(redirectUrl); + if (canonicalUrl) return !isCurrentPage(canonicalUrl); + return true; +}; diff --git a/src/components/ReferralBlock/types.ts b/src/components/ReferralBlock/types.ts new file mode 100644 index 00000000..b0875000 --- /dev/null +++ b/src/components/ReferralBlock/types.ts @@ -0,0 +1,109 @@ +export interface Referrals { + statusCode: number; + message: string; + result: Result; +} + +interface Result { + date_modified: Date; + pagination: Pagination; + fetch_type: string; + title: string; + articles: Article[]; +} + +export interface Article { + id: string; + canonical_url: string; + basic_headline: string; + title: string; + lead_art: LeadArt; + description: string; + web: string; + content_code: string; + updated_time: Date; + published_time: Date; + display_time: Date; + thumbnail: LeadArt; + primary_media_type: string; + source: Source; + redirect_url: string; + distributor: string; + authors: Author[]; + kicker: Kicker; + content_elements: unknown[]; + headline_category?: unknown; + content?: { + third_party?: unknown; + }; +} + +interface Author { + topic_url: string; + thumbnail: Thumbnail; + id: string; + name: string; + first_name: string; + last_name: string; + company: string; + social_links: SocialLink[]; + byline: string; +} + +interface SocialLink { + url: string; + site: string; +} + +interface Thumbnail { + url: string; + resizer_url: string; + renditions: Renditions; +} + +interface Renditions { + square: Landscape; + landscape: Landscape; + portrait: Landscape; + original: Landscape; +} + +interface Landscape { + '60w': string; + '120w': string; + '240w': string; + '480w': string; + '960w': string; + '1080w': string; + '1200w': string; + '1920w': string; +} + +interface Kicker { + name: string; + path: string; + names: string[]; +} + +interface LeadArt { + type: string; + url: string; + resizer_url: string; + renditions: Renditions; + id: string; + caption?: string; + alt_text: string; + width: number; + height: number; + subtitle: string; + updated_at: Date; +} + +interface Source { + name: string; +} + +interface Pagination { + size: number; + expected_size: number; +}