Add channel link to the suggested videos thumbnails
// ==UserScript==
// @name Youtube - add channel link
// @namespace https://github.com/Procyon-b
// @version 0.6.15
// @description Add channel link to the suggested videos thumbnails
// @author Achernar
// @match https://www.youtube.com/*
// @run-at document-start
// @grant none
// ==/UserScript==
(function() {
"use strict";
var iST=`
._chan_lnk {
color: inherit;
text-decoration: none;
}
:is(.yt-content-metadata-view-model__metadata-row,.ytContentMetadataViewModelMetadataRow):first-of-type:hover > * {
white-space: normal !important;
word-break: break-all !important;
}
yt-lockup-metadata-view-model span:has(._chan_lnk) {
cursor: default;
}
yt-lockup-view-model a._chan_lnk:hover, ytd-compact-video-renderer a._chan_lnk:hover *,
yt-lockup-view-model a._chan_lnk:visited:hover, ytd-compact-video-renderer a._chan_lnk:visited:hover * {
color: var(--yt-attributed-string-link-hover-color) !important;
}
`;
var vc={}, vct=0;
function init() {
var root, cfg={childList:true, subtree:true};
var obs=new MutationObserver(function(mutL){
for (let m of mutL) {
if (!m.addedNodes.length) continue;
let YLVM, wall, grid;
// 20250701 new layout
if ( (m.target.tagName == 'YT-LOCKUP-VIEW-MODEL') ) YLVM=true;
else if ( (m.target.tagName == 'YTD-CHANNEL-NAME') ) ; // shorts thumbnails are generated differently
else if (m.target.classList.contains('ytp-videowall-still-info-author')) wall=true;
else if (m.target.classList.contains('yt-lockup-view-model__metadata')) YLVM=true; // first thumbnail is slowly built
else if (m.target.classList.contains('ytLockupViewModelMetadata')) YLVM=true; // 20260408 new names
//else if (m.target.classList.contains('ytp-fullscreen-grid-stills-container')) grid=true;
else continue;
let e;
if (YLVM || wall) e=m.target;
else if (grid) e=m.addedNodes[0];
else e=m.target.closest('ytd-compact-video-renderer ytd-channel-name, ytd-compact-playlist-renderer .ytd-channel-name, .ytp-videowall-still-info .ytp-videowall-still-info-author');
if (!e) continue;
e.dataset._c_= parseInt(e.dataset._c_ || 0)+1;
let vl=e._a
if (!vl) {
if (YLVM ) vl=e.querySelector('a:is(.yt-lockup-metadata-view-model__title,.ytLockupMetadataViewModelTitle)');
else vl=e.closest('a');
}
if (!vl || (!vl.href && !vl.href0) ) continue;
if (e._done && (vl.href0 == vl.href) ) continue;
vl.href0=vl.href;
vl.dataset.href0=vl.href;
e._done=1;
e.dataset._cd_= parseInt(e.dataset._cd_ || 0)+1;
e.classList.add('_a-ed_');
let id=vl.dataset.url0?.split('&list=')[1]?.split('&')[0] || vl.href.split('&list=')[1]?.split('&')[0]
|| vl.href.split('v=')[1]?.split('&')[0] || vl.href.split('/shorts/')[1];
if (!id) continue;
let cid=vc[id];
if (!cid) {
if (e._a) e.parentNode.removeAttributeNode(e.parentNode.getAttributeNode('href'));
continue;
}
let r;
if (YLVM || grid) r=e;
else r=e.parentElement;
let a=e._a ? r : document.createElement('a');
obs.disconnect();
if (typeof(cid)=='object') {
a.removeAttribute('href');
if (YLVM) {
r=r.querySelector('yt-lockup-metadata-view-model :is(.yt-lockup-metadata-view-model__metadata,.ytLockupMetadataViewModelMetadata) > yt-content-metadata-view-model > div:first-child span span');
if (r) {
let s2='', c=[];
for (let k in cid) {
c.push(k.replace(/([.?\\|()[\]*+{}])/g, "\\$1"));
}
c='('+c.join('|')+')';
for (let k in cid) {
if (s2) s2+='(\\s?(?:.*?(?:\\s|$))?)?';
s2+=c+'?';
}
s2='^'+s2+'$';
let RE2=(new RegExp(s2)).exec(r.innerText);
if (RE2 && RE2.length) {
for (let i=r.childNodes.length-1; i >= 0; i--) {
r.removeChild(r.childNodes[i]);
}
}
var i, C=Object.assign({}, cid);
for (i=1; i < RE2.length; i++) {
let k;
if (k=RE2[i]) {
if (C[k]) {
let sp=document.createElement('a');
sp.className='multiLnk _chan_lnk';
let c=cid[k];
if (c && (c[0] != '/') ) c='/'+c;
sp.href=c;
sp.innerText=k;
r.append(sp);
delete C[k];
}
else {
r.append(k);
}
}
}
i=1;
for (let K in C) {
let sp=document.createElement('a');
sp.className='moreChans _chan_lnk';
let c=C[K];
if (c && (c[0] != '/') ) c='/'+c;
sp.href=c;
sp.innerText='['+(i)+']';
r.append(' ',sp);
i++;
}
}
}
}
else {
a.href=cid;
a.className='_chan_lnk';
let e0=e;
if (YLVM) {
r=r.querySelector('yt-lockup-metadata-view-model :is(.yt-lockup-metadata-view-model__metadata,.ytLockupMetadataViewModelMetadata) > yt-content-metadata-view-model > div:first-child');
e0=r.querySelector('span');
}
else if (grid) {
e0=r.querySelector('.ytp-modern-videowall-still-info-author');
}
if (!e._a) {
if (grid) {
a.appendChild(e0.childNodes[0]);
a.addEventListener('click', click);
e0.appendChild(a);
}
else {
a.appendChild(e0);
a.addEventListener('click', click);
r.appendChild(a);
}
e._a=vl;
}
}
obs.observe(document, cfg);
}
});
obs.observe(document, cfg);
if (iST) addSt();
fill_cv();
}
function click(ev) {
ev.stopPropagation();
}
function fill_cv() {
try{
var cvr=ytInitialData.contents.twoColumnWatchNextResults.secondaryResults.secondaryResults.results;
parseAr(cvr);
}catch(e){}
try{
parseAr(ytInitialData.playerOverlays.playerOverlayRenderer.endScreen.watchNextEndScreenRenderer.results);
}catch(e){}
}
if (document.readyState != 'loading') init();
else document.addEventListener('DOMContentLoaded', init);
window.vc=vc;
function addSt() {
if (!iST) return;
try {
let ST=document.createElement('style');
document.documentElement.appendChild(ST);
ST.textContent=iST;
iST='';
}catch(e){
setTimeout(addSt,0); }
}
function parseAr(a) {
if (a.length == 1) {
let a2=a[0].itemSectionRenderer?.contents;
if (a2) a=a2;;
}
for (let v of a) {
let vid, cid, t;
try{
vid=v.compactVideoRenderer.videoId;
t=v.compactVideoRenderer.shortBylineText.runs[0].navigationEndpoint.browseEndpoint;
cid=t.canonicalBaseUrl || t.browseId;
}catch(e){
try{
vid=v.endScreenVideoRenderer.videoId;
t=v.endScreenVideoRenderer.shortBylineText.runs[0].navigationEndpoint.browseEndpoint;
cid=t.canonicalBaseUrl || t.browseId;
}catch(e){
try{
vid=v.compactPlaylistRenderer.playlistId;
t=v.compactPlaylistRenderer.shortBylineText.runs[0].navigationEndpoint.browseEndpoint;
cid=t.canonicalBaseUrl || t.browseId;
}catch(e){
try{
vid=v.lockupViewModel.contentId;
t=v.lockupViewModel.metadata.lockupMetadataViewModel.image.decoratedAvatarViewModel.rendererContext.commandContext.onTap.innertubeCommand.browseEndpoint;
cid=t.canonicalBaseUrl || t.browseId;
}catch(e){
try{
vid=v.lockupViewModel.contentId;
let multi=v.lockupViewModel.metadata.lockupMetadataViewModel.image.avatarStackViewModel.rendererContext.commandContext.onTap.innertubeCommand.showDialogCommand.panelLoadingStrategy.inlineContent.dialogViewModel.customContent.listViewModel.listItems;
let chans={};
for (let c of multi) {
let n=c.listItemViewModel.title.content.trim();
let ch=c.listItemViewModel.subtitle.content.split(/[^\w@]/)[2];
chans[n]=ch;
}
cid=chans;
}catch(e){}
} } } }
if (vid && cid) {
if ( (typeof cid == 'string') && !cid.startsWith('/@') && !cid.startsWith('/channel/') ) cid='/channel/'+cid;
vc[vid]=cid;}
}
}
// JSON.parse
var JP=JSON.parse;
JSON.parse=function(){
var a, r=JP(...arguments);
try{if (a=r?.onResponseReceivedEndpoints?.[0]?.appendContinuationItemsAction?.continuationItems) {
parseAr(a);
}
}catch(a){}
try{if (a=r?.contents?.twoColumnWatchNextResults?.secondaryResults?.secondaryResults?.results) {
parseAr(a);
}
}catch(a){}
try{if (a=r?.watchNextResponse?.contents?.twoColumnWatchNextResults?.secondaryResults?.secondaryResults?.results) {
parseAr(a);
}
}catch(a){}
return r;
}
})();