From 4cd79c037d1b66438fcf88ea72c6acd7b604c409 Mon Sep 17 00:00:00 2001 From: Mohammad Jafari Date: Thu, 26 Oct 2023 15:44:02 +0330 Subject: [PATCH 1/4] Add OpenGraph preview Create OpenGraphPreview component to fetch and parse metadata. Integrate into LinkPreview to show if no other preview available. Implement polished styling for clean, readable design. --- src/components/link-preview/open-graph.jsx | 39 ++++++++++++++++++++ src/components/link-preview/preview.jsx | 6 ++-- styles/shared/post.scss | 42 ++++++++++++++++++++++ 3 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 src/components/link-preview/open-graph.jsx diff --git a/src/components/link-preview/open-graph.jsx b/src/components/link-preview/open-graph.jsx new file mode 100644 index 000000000..a4620ec95 --- /dev/null +++ b/src/components/link-preview/open-graph.jsx @@ -0,0 +1,39 @@ +import { useEffect, useState } from 'react'; + +export default function OpenGraphPreview({ url }) { + const [data, setData] = useState(null); + + useEffect(() => { + async function fetchData() { + const response = await fetch(url); + const html = await response.text(); + const doc = new DOMParser().parseFromString(html, 'text/html'); + + const metaContent = (property) => + doc.querySelector(`meta[property="${property}"]`)?.getAttribute('content'); + + const [title, description, image, source] = [ + 'og:title', + 'og:description', + 'og:image', + 'og:site_name', + ].map(metaContent); + setData({ title, description, image, source }); + } + fetchData(); + }, [url]); + if (!data || data.title === undefined) { + return null; + } + + return ( +
+ {data.image && {data.title}} +
+
{data.title}
+
{data.description}
+
{data.source}
+
+
+ ); +} diff --git a/src/components/link-preview/preview.jsx b/src/components/link-preview/preview.jsx index 39a8b51a5..fca83c35b 100644 --- a/src/components/link-preview/preview.jsx +++ b/src/components/link-preview/preview.jsx @@ -11,7 +11,7 @@ import TikTokPreview, { canShowURL as tikTokCanShowURL } from './tiktok'; import SoundCloudPreview, { canShowURL as soundCloudCanShowURL } from './soundcloud'; import SpotifyPreview, { canShowURL as spotifyCanShowURL } from './spotify'; import AppleMusicPreview, { canShowUrl as appleMusicCanShowURL } from './apple-music'; - +import OpenGraphPreview from './open-graph'; import EmbedlyPreview from './embedly'; export default function LinkPreview({ allowEmbedly, url }) { @@ -41,12 +41,10 @@ export default function LinkPreview({ allowEmbedly, url }) { } else if (appleMusicCanShowURL(url)) { return ; } - if (allowEmbedly) { return ; } - - return false; + return ; } LinkPreview.propTypes = { diff --git a/styles/shared/post.scss b/styles/shared/post.scss index 3618fd80b..32b7b44ef 100644 --- a/styles/shared/post.scss +++ b/styles/shared/post.scss @@ -772,6 +772,48 @@ $post-line-height: rem(20px); .tiktok-video-iframe { width: 100%; } + + .opengraph-preview { + max-width: 500px; + border-radius: 10px; + padding: 10px; + margin-top: 10px; + margin-bottom: 10px; + background-color: #f8f8f8; + border: 1px solid #555; + .dark-theme & { + background-color: #222; + } + } + + .opengraph-image { + max-width: 100%; + max-height: 300px; + } + + .opengraph-title { + font-size: 1.2em; + margin-top: 0.5em; + color: #111; + .dark-theme & { + color: #d9d9d9; + } + } + + .opengraph-description { + font-size: 1em; + margin-top: 0.5em; + color: #333; + .dark-theme & { + color: #a9a9a9; + } + } + + .opengraph-source { + font-size: 1em; + margin-top: 0.5em; + color: #777; + } } .submit-mode-hint { From 4e1930c6e90ecfde451984ff8ba15db429383677 Mon Sep 17 00:00:00 2001 From: Mohammad Jafari Date: Thu, 26 Oct 2023 15:56:40 +0330 Subject: [PATCH 2/4] Update changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 821aa1490..3ab5746ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [1.125.0] - Not released +### Added +- Add OpenGraphPreview component and integrate into LinkPreview + - Add OpenGraphPreview component to fetch and parse Open Graph metadata from pages + - Integrated OpenGraphPreview into LinkPreview to show open graph preview if no other specific preview available for a URL + - Created thoughtful styling for the OpenGraphPreview for a clean, polished, and readable design + - OpenGraphPreview provides a fallback preview option for sites that implement Open Graph metadata + - Parsing logic simplified using DOMParser and meta tag selectors + +### Changed +- Update LinkPreview component to check for Open Graph data and show OpenGraphPreview ## [1.124.2] - 2023-10-25 ### Fixed From eb7b77f6f4b32496f99eb5f06929a1bf923fa890 Mon Sep 17 00:00:00 2001 From: Mohammad Jafari Date: Fri, 27 Oct 2023 16:13:20 +0330 Subject: [PATCH 3/4] Exclude internal URLs and subpaths Exclude internal URLs and subpaths (i.e., URLs that start with the same origin as the current window location) from being checked for Open Graph tags --- src/components/link-preview/open-graph.jsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/link-preview/open-graph.jsx b/src/components/link-preview/open-graph.jsx index a4620ec95..f02000afd 100644 --- a/src/components/link-preview/open-graph.jsx +++ b/src/components/link-preview/open-graph.jsx @@ -4,6 +4,9 @@ export default function OpenGraphPreview({ url }) { const [data, setData] = useState(null); useEffect(() => { + if (url.startsWith(window.location.origin)) { + return; + } async function fetchData() { const response = await fetch(url); const html = await response.text(); From 117c88e4d76ef7776ab7de9ed606b43056a37411 Mon Sep 17 00:00:00 2001 From: Mohammad Jafari Date: Fri, 27 Oct 2023 16:15:31 +0330 Subject: [PATCH 4/4] Use CORS proxy to fetch OG tags for websites that do not have CORS access This change will allow us to display link previews for websites that we were not able to display them for before --- src/components/link-preview/open-graph.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/link-preview/open-graph.jsx b/src/components/link-preview/open-graph.jsx index f02000afd..1d9f22dd0 100644 --- a/src/components/link-preview/open-graph.jsx +++ b/src/components/link-preview/open-graph.jsx @@ -8,7 +8,7 @@ export default function OpenGraphPreview({ url }) { return; } async function fetchData() { - const response = await fetch(url); + const response = await fetch(`https://corsproxy.io/?${encodeURIComponent(url)}`); const html = await response.text(); const doc = new DOMParser().parseFromString(html, 'text/html');