diff --git a/brave-extension/popup.js b/brave-extension/popup.js index 4e1fd6d..b89c41c 100644 --- a/brave-extension/popup.js +++ b/brave-extension/popup.js @@ -101,6 +101,22 @@ async function handleClip() { // Clone document and resolve lazy-loaded images & relative URLs inside the live tab const clone = document.documentElement.cloneNode(true); clone.querySelectorAll('script, style, noscript, iframe').forEach((el) => el.remove()); + clone.querySelectorAll('[aria-hidden="true"]').forEach((el) => { + if (el.tagName !== 'svg' && el.tagName !== 'dialog') { + el.removeAttribute('aria-hidden'); + } + }); + clone.querySelectorAll('[hidden]').forEach((el) => el.removeAttribute('hidden')); + clone.querySelectorAll('details').forEach((d) => d.setAttribute('open', '')); + clone.querySelectorAll('[style]').forEach((el) => { + const s = el.getAttribute('style') || ''; + if (s.includes('display:') || s.includes('visibility:')) { + const cleaned = s + .replace(/display\s*:\s*none\s*;?/gi, '') + .replace(/visibility\s*:\s*hidden\s*;?/gi, ''); + el.setAttribute('style', cleaned); + } + }); clone.querySelectorAll('img').forEach((img) => { const best = img.getAttribute('data-img-url') || diff --git a/src/app/api/extension/route.ts b/src/app/api/extension/route.ts index 78ec5c1..72f3082 100644 --- a/src/app/api/extension/route.ts +++ b/src/app/api/extension/route.ts @@ -195,6 +195,22 @@ async function handleClip() { // Clone document and resolve lazy-loaded images & relative URLs inside the live tab const clone = document.documentElement.cloneNode(true); clone.querySelectorAll('script, style, noscript, iframe').forEach((el) => el.remove()); + clone.querySelectorAll('[aria-hidden="true"]').forEach((el) => { + if (el.tagName !== 'svg' && el.tagName !== 'dialog') { + el.removeAttribute('aria-hidden'); + } + }); + clone.querySelectorAll('[hidden]').forEach((el) => el.removeAttribute('hidden')); + clone.querySelectorAll('details').forEach((d) => d.setAttribute('open', '')); + clone.querySelectorAll('[style]').forEach((el) => { + const s = el.getAttribute('style') || ''; + if (s.includes('display:') || s.includes('visibility:')) { + const cleaned = s + .replace(/display\s*:\s*none\s*;?/gi, '') + .replace(/visibility\s*:\s*hidden\s*;?/gi, ''); + el.setAttribute('style', cleaned); + } + }); clone.querySelectorAll('img').forEach((img) => { const best = img.getAttribute('data-img-url') || diff --git a/src/lib/importers.ts b/src/lib/importers.ts index 66f4733..1db95cd 100644 --- a/src/lib/importers.ts +++ b/src/lib/importers.ts @@ -589,6 +589,29 @@ export function prepareDomForReadability(doc: Document, baseUrl: string): { hero } }); + // 6. Unhide all carousel/slideshow slides, recipe roundups, listicles, tabs, and accordions + // so Readability's _isProbablyVisible() does not prune them. + doc.querySelectorAll('[aria-hidden="true"]').forEach((el) => { + if (el.tagName !== 'svg' && el.tagName !== 'dialog') { + el.removeAttribute('aria-hidden'); + } + }); + doc.querySelectorAll('[hidden]').forEach((el) => { + el.removeAttribute('hidden'); + }); + doc.querySelectorAll('details').forEach((d) => { + d.setAttribute('open', ''); + }); + doc.querySelectorAll('[style]').forEach((el) => { + const s = el.getAttribute('style') || ''; + if (s.includes('display:') || s.includes('visibility:')) { + const cleaned = s + .replace(/display\s*:\s*none\s*;?/gi, '') + .replace(/visibility\s*:\s*hidden\s*;?/gi, ''); + el.setAttribute('style', cleaned); + } + }); + return { heroImgSrc }; }