From 3d91b334d77822ca30ea899fd998968107adef9c Mon Sep 17 00:00:00 2001 From: Write <541722+Write@users.noreply.github.com> Date: Tue, 26 May 2026 16:27:20 +0000 Subject: [PATCH] =?UTF-8?q?R=C3=A9-=C3=A9criture=20de=20l'injection=20du?= =?UTF-8?q?=20bouton=20lib=C3=A9ration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ophirofox/content_scripts/liberation.css | 25 ++++- ophirofox/content_scripts/liberation.js | 125 ++++++++++------------- 2 files changed, 72 insertions(+), 78 deletions(-) diff --git a/ophirofox/content_scripts/liberation.css b/ophirofox/content_scripts/liberation.css index 175e7c4..e9774be 100644 --- a/ophirofox/content_scripts/liberation.css +++ b/ophirofox/content_scripts/liberation.css @@ -1,16 +1,31 @@ .ophirofox-europresse { font-size: 0.875rem; - padding: 5px 10px; background-color: rgb(250, 235, 29); + font-family: TiemposText; color: #000; border-radius: 4px; text-decoration: none; - display: block; - margin-top: -2rem; /* negative margin to pull it up next to h1 */ - margin-left: auto; /* pushes to right if there's space */ width: fit-content; + display: flex; + float: left; + padding: 0px 5px 0px 5px; + margin-right: 0.75rem; + row-gap: 4px; + column-gap: 4px; + height: 1.5rem; + padding-top: 0px; + padding-right: 4px; + -webkit-box-align: center; + align-items: center; + background-color: rgb(250, 235, 29); + width: max-content; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; } .ophirofox-europresse:hover { - color: #666666; + text-decoration: underline; + color: #000; } \ No newline at end of file diff --git a/ophirofox/content_scripts/liberation.js b/ophirofox/content_scripts/liberation.js index 9121cc4..259f8b1 100644 --- a/ophirofox/content_scripts/liberation.js +++ b/ophirofox/content_scripts/liberation.js @@ -4,100 +4,79 @@ function extractKeywords() { .getAttribute("content"); } -/** - * Crée un lien vers Europresse avec les keywords donnés - * @param {string} publishedTime - article publication date (2024-01-01) - * @returns {Promise} - */ async function createLink(publishedTime) { const a = await ophirofoxEuropresseLink(extractKeywords(), { publishedTime: publishedTime }); return a; } function findPremiumBanner() { - const anchor = document.querySelector('div[class^=article-body-paywall]'); - if (!anchor) { - return; - } - return anchor; + return document.querySelector('div[class^=article-body-paywall]') || null; +} + +function findInsertionPoint() { + const target = 'Réservé aux abonnés'.normalize('NFC'); + const el = [...document.querySelectorAll('span')].find( + s => s.textContent.normalize('NFC').trim() === target + ); + return el?.parentElement ?? null; +} + +async function injectLink(publishedDate) { + if (document.querySelector('div[class^=article-body-paywall] + a.ophirofox-europresse')) return; + const anchor = findInsertionPoint(); + if (!anchor) return; + const link = await createLink(publishedDate); + anchor.after(link); + console.log('Ophirofox injected'); } -async function onLoad(premiumBanner) { - /* - The UI is reactive (and DOM rewritten), so we need to wait for some nodes to be rewritten to the DOM - before we can add our link. It seems that the React components are added to the DOM in a particular order. +function resolvePublishedDate() { + let publishedDate = document.querySelector( + "meta[property='article:published_time'], meta[property='og:article:published_time'], meta[property='date:published_time']" + )?.getAttribute("content") || ''; + + const fusionMetadata = document.getElementById('fusion-metadata'); + if (fusionMetadata?.textContent) { + const match = /"first_publish_date":"(\d{4}-\d{2}-\d{2}[A-Z]+\d{2}:\d{2}:\d{2}\.[0-9+-:]+Z)"/.exec(fusionMetadata.textContent); + if (match) { + const firstPublishedDateInstance = new Date(match[1]); + if (!isNaN(firstPublishedDateInstance)) { + if (!publishedDate.trim() || firstPublishedDateInstance < new Date(publishedDate)) { + publishedDate = match[1]; + } + } + } else { + console.error("No match for 'first_publish_date' found."); + } + } else { + console.error("'fusion-metadata' element not found or empty."); + } - With heavy loading, the MutationObserver execution is too late, and only catch .dossier-feed class. - After caching, we can rely on the .article-body-paywall added node. + return publishedDate; +} - Weird choices for a nearly-static content-driven website with SEO concerns. - */ +async function onLoad() { const observer = new MutationObserver(async mutationsList => { for (let mutation of mutationsList) { if (mutation.addedNodes.length > 0) { const addedNode = mutation.addedNodes[0]; - if (addedNode.classList.contains('dossier-feed') || + if ( + addedNode.classList.contains('dossier-feed') || addedNode.classList.contains('article-body-paywall') ) { observer.disconnect(); - - // Not sure if premiumBanner is (and will be) still valid after DOM rewrite - if (!document.querySelector('div[class^=article-body-paywall] + a.ophirofox-europresse')) { - // See #239, Libération replaces date:published_time with the date of edit, which means that a search limited by the time of publication may be too restrictive - // We need to specify the date to use for the generic ophirofoxEuropresseLink function - // Might need refactor if other medias have the same problem, more properties for fail-safe - let publishedDate = document.querySelector("meta[property='article:published_time'], meta[property='og:article:published_time'], meta[property='date:published_time']")?.getAttribute("content") || ''; - - let firstPublishedDate = null; - let firstPublishedDateInstance = null; - - let fusionMetadata = document.getElementById('fusion-metadata'); - if (fusionMetadata && fusionMetadata.textContent) { - let match = /"first_publish_date":"(\d{4}-\d{2}-\d{2}[A-Z]+\d{2}:\d{2}:\d{2}\.[0-9+-:]+Z)"/.exec(fusionMetadata.textContent); // 2024-08-27T18:18:55.663Z => UTC - if (match) { - firstPublishedDate = match[1]; - firstPublishedDateInstance = new Date(firstPublishedDate); - } else { - console.error("No match for 'first_publish_date' found."); - } - } else { - console.error("'fusion-metadata' element not found or empty."); - } - - // Check if publishedDate exists and is not empty - if (publishedDate && publishedDate.trim()) { - // If the first published date is valid and older - if (firstPublishedDateInstance && !isNaN(firstPublishedDateInstance) && (firstPublishedDateInstance < new Date(publishedDate))) { - publishedDate = firstPublishedDate; - } - } else { - // If published date is empty or invalid, use firstPublishedDate if available - if (firstPublishedDateInstance && !isNaN(firstPublishedDateInstance)) { - publishedDate = firstPublishedDate; - } - } - - const link = await createLink(publishedDate); - document.querySelector('h1').after(link); - - console.log('Ophirofox injected after React DOM rewrite'); - break; - } + await injectLink(resolvePublishedDate()); + break; } } } }); - observer.observe(document.body, { - childList: true, - subtree: true - }); + observer.observe(document.body, { childList: true, subtree: true }); } -createLink().then(link => { - const premiumBanner = findPremiumBanner(); - if (premiumBanner) { - premiumBanner.after(link); - console.log('Ophirofox injected'); +(async () => { + if (findPremiumBanner()) { + await injectLink(resolvePublishedDate()); } - onLoad(premiumBanner); -}); \ No newline at end of file + onLoad(); +})(); \ No newline at end of file