Pixiv Direct Links

Turns thumbnail titles into direct or mode=manga links, adds direct image links on mode=manga pages, replaces the medium thumbnail on mode=medium pages with the full size, and disables lazy-loading images.

当前为 2016-06-09 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name           Pixiv Direct Links
// @namespace      https://greasyfork.org/scripts/4555
// @description    Turns thumbnail titles into direct or mode=manga links, adds direct image links on mode=manga pages, replaces the medium thumbnail on mode=medium pages with the full size, and disables lazy-loading images.
// @include        http://www.pixiv.net/*
// @grant          none
// @version        2016.06.08
// ==/UserScript==

//Turn thumbnail titles into direct links (single images) or mode=manga links.  Some kinds of thumbnails aren't covered, and an isolated few (like #17099702) don't work.
var directTitles = false;

//Append direct links below images on mode=manga pages
var directManga = true;

//Force pixiv's 'book view' style for manga sequences to something like the normal view.  Clicking a page won't scroll the window to the next page.
var breakBookView = false;

//Replace the medium thumbnail on mode=medium pages with the full size.  The image will be relinked to the full size regardless of this setting.
var fullSizeMedium = true;

//Disable lazy loading images.  These appear on mode=manga pages, rankings, and the "Recommended" section of the bookmarks page.
var dontSayLazy = true;

//----------------------------------------------------------------//

var fullSizeWidth = "740px";

if( typeof(custom) != "undefined" )
	custom();

if( location.search.indexOf("mode=manga_big") > 0 || location.search.indexOf("mode=big") > 0 )
{
	//Make the 'big'/'manga_big' image link to itself instead of closing the window
	var image = document.getElementsByTagName("img")[0];
	if( image )
	{
		var link = document.createElement("a");
		link.href = image.src;
		link.appendChild( document.createElement("img") ).src = image.src;
		document.body.innerHTML = "";
		document.body.appendChild( link );
	}
}
else if( location.search.indexOf("mode=manga") > 0 )
{
	var container = document.getElementsByClassName("full-size-container");
	if( directManga && container.length )
	{
		//Check the mode=manga_big page for the first page to determine if the "_big_p" size exists.
		var req = new XMLHttpRequest();
		req.open( "GET", location.href.replace(/page=\d+&?/,'').replace('mode=manga','mode=manga_big&page=0'), true );
		req.onload = function()
		{
			var firstImage = req.responseXML.querySelector("img[src*='_p0.']").src;
			for( var i = 0; i < container.length; i++ )
			{
				//Add direct link below each page
				var link = document.createElement("a");
				link.textContent = "direct link";
				link.style.display = "block";
				link.href = firstImage.replace( "_p0.", "_p"+i+"." );
				container[i].parentNode.appendChild( link );
			}
		};
		req.responseType = "document";
		req.send(null);
	}
	else if( breakBookView && document.head.innerHTML.indexOf("pixiv.context.images") > 0 )
	{
		//Book view (e.g. #54139174, #57045668)

		var mangaSection = document.createElement("section");
		mangaSection.className = "manga";
		
		var scripts = document.head.getElementsByTagName("script");
		var hits = 0;
		for( var i = 0; i < scripts.length; i++ )
		{
			var urls = scripts[i].innerHTML.match( /pixiv.context.images[^"]+"([^"]+)".*pixiv.context.originalImages[^"]+"([^"]+)"/ );
			if( urls )
			{
				var full = urls[2].replace( /\\\//g, "/");
				mangaSection.innerHTML += '<div class="item-container"><a href="'+full+'" class="full-size-container"><i class="_icon-20 _icon-full-size"></i></a><img style="width:auto;height:auto;max-width:1200px;max-height:1200px" src="'+full+'" class="image">'+( directManga ? '<a href="'+full+'" style="display:block">direct link</a>' : '' )+'</div>';
				hits++;
			}
		}
		
		if( hits > 0 )
		{
			var sheet = document.createElement("link");
			sheet.setAttribute("rel","stylesheet");
			sheet.setAttribute("href","http://source.pixiv.net/www/css/member_illust_manga.css");
			document.head.appendChild( sheet );
			document.getElementsByTagName("html")[0].className = "verticaltext no-textcombine no-ie";
			document.body.innerHTML = "";
			document.body.appendChild( mangaSection );
		}
	}
}
else if( window == window.top )//not inside iframe
{
	if( directTitles )
	{
		//Link dem titles.
		linkThumbTitles([document]);
		new MutationObserver( function(mutationSet)
		{
			mutationSet.forEach( function(mutation){ linkThumbTitles( mutation.addedNodes ); } );
		}).observe( document.body, { childList:true, subtree:true } );
	}
	
	var worksDisplay = document.getElementsByClassName("works_display")[0];
	if( worksDisplay )
	{
		var mainImage, mainLink = worksDisplay.querySelector("a[href*='mode=']");
		if( mainLink )
			mainLink.removeAttribute('target');//Make link open in same window
		
		var oClass = document.getElementsByClassName("original-image");
		if( oClass.length == 1 )//47235071
		{
			var worksDiv = worksDisplay.getElementsByTagName("div")[0];
			worksDisplay.removeChild( worksDiv );//Need to remove instead of hide to prevent double source search links in other script
			var link = worksDisplay.insertBefore( document.createElement("a"), worksDisplay.firstChild );
			mainImage = link.appendChild( fullSizeMedium ? document.createElement("img") : worksDiv.getElementsByTagName("img")[0] );
			fullsizeSrc = link.href = oClass[0].getAttribute("data-src");
		}
		else if( mainLink && mainLink.href.indexOf("mode=big") > 0 && (mainImage = mainLink.getElementsByTagName("img")[0]) !== null )//17099702
		{
			if( mainImage.src.indexOf("_m.") > 0 )
				mainLink.href = fullsizeSrc = mainImage.src.replace("_m.",".");
			else
			{
				//New thumbnails are always jpg, need to query mode=big page to get the right file extension.
				var req = new XMLHttpRequest();
				req.open( "GET", mainLink.href, true );
				req.onload = function()
				{
					mainLink.href = req.responseXML.getElementsByTagName("img")[0].src;
					if( fullSizeMedium )
						mainImage.src = mainLink.href;
				}
				req.responseType = "document";
				req.send(null);
			}
		}
		
		if( mainImage && fullSizeMedium )
		{
			if( fullsizeSrc )
				mainImage.src = fullsizeSrc;
			mainImage.setAttribute("style", "max-width: "+fullSizeWidth+"; height: auto; width: auto;");
			worksDisplay.style.width = fullSizeWidth;
		}
	}
}

if( dontSayLazy && unlazyImage() && window == window.top )
{
	//Initial page has lazy images; listen for more images added later
	new MutationObserver( function(mutationSet)
	{
		mutationSet.forEach( function(mutation)
		{
			for( var i = 0; i < mutation.addedNodes; i++ )
				unlazyImage( mutation.addedNodes[i] );
		} );
	}).observe( document.body, { childList:true, subtree:true } );
}

//----------------------------------------------------------------//

function unlazyImage(target)
{
	var images = ( target || document ).querySelectorAll("img[data-src]");
	for( var i = 0; i < images.length; i++ )
		images[i].src = images[i].getAttribute("data-src");
	return images.length;
}

function pushTitleLink(list, link)
{
	var matcher;
	if( link && link.href && (matcher = link.href.match(/illust_id=(\d+)/)) && matcher[1] > 0 )
		list.push({ "id": matcher[1], "link": link });
}

function linkThumbTitles(targets)
{
	var titleList = [];
	
	for( var i = 0; i < targets.length; i++ )
	{
		//search.php, bookmark.php, member_illust.php, new_illust.php, member.php (uploads), mypage.php (new works)
		var foundTitle = targets[i].querySelectorAll("a[href*='mode=medium'][href*='illust_id='] > .title");
		for( var j = 0; j < foundTitle.length; j++ )
			pushTitleLink( titleList, foundTitle[j].parentNode );
		
		//ranking.php
		foundTitle = targets[i].querySelectorAll(".ranking-item a.title[href*='mode=medium'][href*='illust_id=']");
		for( var j = 0; j < foundTitle.length; j++ )
			pushTitleLink( titleList, foundTitle[j] );
		
		//member_illust.php (what image was responding to)
		foundTitle = targets[i].querySelector(".worksImageresponseInfo a.response-out-work[href*='mode=medium'][href*='illust_id=']");
		if( foundTitle )
			pushTitleLink( titleList, foundTitle );
		
		//response.php, member_illust.php (before/after thumbnails), ?member.php (bookmarks)?
		var image = targets[i].querySelectorAll("li a[href*='mode=medium'][href*='illust_id='] img");
		for( var j = 0; j < image.length; j++ )
		{
			var page, title;
			for( page = image[j].parentNode; page.tagName != "A"; page = page.parentNode );
			
			//The prev/next thumbnails on mode=medium pages have text before/after the image.  Text also follows the image on image responses listings.
			if( !(title = page.getElementsByClassName("title")[0]) && (title = page.lastChild).nodeName != '#text' && (title = page.firstChild).nodeName != '#text' )
				continue;//Can't find title element
			
			//Start title link at mode=medium and change later.
			var titleLink = document.createElement("a");
			titleLink.href = page.href;
			titleLink.style.color = "#333333";//Style used on some pages
			
			//Move the title out of the thumbnail link
			page.removeChild(title);
			titleLink.appendChild(title);
			page.parentNode.insertBefore( titleLink, page.nextSibling );
			
			pushTitleLink( titleList, titleLink );
		}
	}
	
	for( var i = 0; i < titleList.length; i++ )
		directLinkSingle( titleList[i] );
}

//Query an image's mode=medium page.
function directLinkSingle(title)
{
	var req = new XMLHttpRequest();
	req.open( "GET", "http://www.pixiv.net/member_illust.php?mode=medium&illust_id="+title.id, true );
	req.onload = function()
	{
		var select = req.responseXML.getElementsByClassName("original-image");
		if( select.length == 1 )
			title.link.href = select[0].getAttribute("data-src");
		else if( (select = req.responseXML.querySelector(".works_display a[href*='mode=big'] img[src*='_m.']")) !== null )
			title.link.href = select.src.replace("_m.",".");
		else if( (select = req.responseXML.querySelector(".works_display a[href*='mode=manga']")) !== null )
		{
			title.link.href = select.href;
			var page = req.responseXML.querySelectorAll("ul.meta li")[1].textContent.match(/(\d+)P$/);
			if( page )
				( title.link.firstChild.nodeName == '#text' ? title.link : title.link.firstChild ).title += " ("+page[1]+" pages)";
		}
	};
	req.responseType = "document";
	req.send(null);
}