Skip to content

Commit

Permalink
wip: progressively enhance thumbnails instead
Browse files Browse the repository at this point in the history
  • Loading branch information
fire332 committed Dec 19, 2024
1 parent 91ff161 commit 2df2b37
Showing 1 changed file with 78 additions and 42 deletions.
120 changes: 78 additions & 42 deletions src/thumbnail-quality.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,67 +38,103 @@ function rewriteURL(url: URL) {
const YT_THUMBNAIL_PATHNAME_REGEX =
/vi(?:_webp)?(\/.*?\/)([a-z0-9]+?)(_\w*?)?\.[a-z]+$/g;

const YT_THUMBNAIL_NAMES = [
'maxresdefault',
'sddefault',
'hqdefault',
'mqdefault',
'default'
] as const;

const isABTest = url.hostname.match(/^i\d/) !== null;
// Don't know how to handle A/B test thumbnails so we don't upgrade them.
if (isABTest) return url.href;
if (isABTest) return null;

const replacementPathname = url.pathname.replace(
YT_THUMBNAIL_PATHNAME_REGEX,
(match, p1, p2, p3) => {
if (
![
'maxresdefault',
'sddefault',
'hqdefault',
'mqdefault',
'default'
].includes(p2)
)
return match; // Only rewrite regular thumbnail URLs. Not shorts, etc.
if (!YT_THUMBNAIL_NAMES.includes(p2)) return match; // Only rewrite regular thumbnail URLs. Not shorts, etc.
return `${webpSupported ? 'vi_webp' : 'vi'}${p1}maxresdefault${p3 ?? ''}.${webpSupported ? 'webp' : 'jpg'}`;
}
);
if (url.pathname === replacementPathname)
// pathname not changed because not a regular thumbnail or already upgraded.
return null;

url = new URL(url);

url.pathname = replacementPathname;
url.search = '';

return url.href;
return url;
}

const origParse = JSON.parse;
function parseCSSUrl(value: string) {
return new URL(value.slice(4, -1).replace(/["']/g, ''));
}

JSON.parse = function (data) {
const res = data.replaceAll(/"h.*?\.ytimg\.com\/vi.*?"/g, (match) => {
const href = rewriteURL(new URL(origParse(match)));
function upgradeBgImg(element: HTMLElement) {
const style = element.style;
const old = parseCSSUrl(style.backgroundImage);

return JSON.stringify(`${href}`);
});
const target = rewriteURL(old);
if (!target) return;

return origParse(res);
};
const lazyLoader = new Image();

function rewriteBgImg(element: HTMLElement) {
console.log(element);
const style = element.style;
console.log('Upgrading', element, target.href);

const url = new URL(style.backgroundImage.slice(4, -1).replace(/["']/g, ''));
lazyLoader.onload = () => {
const curr = parseCSSUrl(style.backgroundImage);

style.backgroundImage = `url(${JSON.stringify(rewriteURL(url))})`;
// Don't swap out element image if it has been changed while target image was loading.
if (curr.href !== old.href) return;

style.backgroundImage = `url(${target.href})`;
};

lazyLoader.src = target.href;
}

// const obs = new MutationObserver((mutations) => {
// mutations
// .map((mut) => mut.target)
// .filter<HTMLElement>(
// (node): node is HTMLElement =>
// node instanceof HTMLElement &&
// node.matches('ytlr-thumbnail-details') &&
// node.style.backgroundImage != undefined
// )
// .forEach(rewriteBgImg);
// });

// obs.observe(document.body, {
// subtree: true,
// attributes: true,
// attributeFilter: ['style']
// });
const YT_THUMBNAIL_ELEMENT_TAG = 'ytlr-thumbnail-details';

const obs = new MutationObserver((mutations) => {
const dummy = document.createElement('div');

// handle backgroundImage change
mutations
.filter((mut) => mut.type === 'attributes')
.map((mut) => [mut.target, mut] as const)
.filter((value): value is [HTMLElement, MutationRecord] => {
const [node, { oldValue }] = value;
dummy.style.cssText = oldValue ?? '';

return (
node instanceof HTMLElement &&
node.matches(YT_THUMBNAIL_ELEMENT_TAG) &&
node.style.backgroundImage !== '' &&
node.style.backgroundImage !== dummy.style.backgroundImage
);
})
.map(([elem]) => elem)
.forEach(upgradeBgImg);

// handle element add
mutations
.filter((mut) => mut.type === 'childList')
.flatMap((mut) => Array.from(mut.addedNodes))
.filter((node) => node instanceof HTMLElement)
.flatMap((elem) =>
Array.from(elem.querySelectorAll<HTMLElement>(YT_THUMBNAIL_ELEMENT_TAG))
)
.filter((elem) => elem.style.backgroundImage !== '')
.forEach(upgradeBgImg);
});

obs.observe(document.body, {
subtree: true,
childList: true,
attributes: true,
attributeFilter: ['style'],
attributeOldValue: true
});

0 comments on commit 2df2b37

Please sign in to comment.