Greasy Fork is available in English.
pixivイラストページのタグに作者マーカーと百科事典アイコン、ユーザー名の列に作品タグを復活させます
当前为
// ==UserScript==
// @name pixivイラストページ改善
// @description pixivイラストページのタグに作者マーカーと百科事典アイコン、ユーザー名の列に作品タグを復活させます
// @namespace Aime
// @match https://www.pixiv.net/member_illust.php*
// @version 1.0.1
// @grant none
// @run-at document-end
// @noframes
// @note 2018/06/22 1.0.1 作者アイコンを大サイズに差し替え
// ==/UserScript==
(() => {
"use strict";
const pixivService = {
enablePixpediaIcon : true, // 百科事典アイコンを付けるか?
enableTagCloud : true, // 作品タグを表示するか?
enableReplaceAuthorIcon : true, // 作者アイコンを大サイズに差し替える?
_existPixpedia : {},
_illustTags : {},
_currenAuthorId : -1,
_delayTimer : null,
run: function() {
const root = document.getElementById("root");
if (!root)
return;
const head = document.querySelector("head");
const style = document.createElement("style");
style.textContent = this._style;
head.appendChild(style);
new MutationObserver(records => {
records.forEach(record => {
if (record.type === "attributes") {
const target = record.target;
if (target.classList.contains("_2lyPnMP") && target.parentElement.classList.contains("_2kZnEk0"))
this.replaceAuthorIcon();
} else {
record.addedNodes.forEach(node => {
if (!node.querySelectorAll)
return;
// 増えたタグに百科事典アイコンを付ける
const tags = node.querySelectorAll("a.gtm-new-work-tag-event-click:not([pixpedia]");
if (tags.length) {
if (this.enablePixpediaIcon)
tags.forEach(node => this.insertPixpedia(node));
this.authorTags();
return;
}
// タグが減ったか変わらない場合は画像が変わったかで判断
// イラスト:img._2r_DywD, うごイラ:div._3QPzwxP, 閲覧注意:div._27qPnrS
if (node.classList.contains("_2r_DywD") || node.classList.contains("_3QPzwxP") || node.classList.contains("_27qPnrS")) {
this.stopDelayTimer();
this._delayTimer = setTimeout(this.illustChanged.bind(this), 1000);
}
});
}
});
}).observe(root, {
childList : true,
subtree : true,
attributes : true,
attributeFilter : [ "style" ]
});
},
stopDelayTimer: function() {
if (this._delayTimer) {
clearTimeout(this._delayTimer);
this._delayTimer = null;
}
},
illustChanged: function() {
this.stopDelayTimer();
this.authorTags();
},
insertPixpedia: async function(node) {
if (node.hasAttribute("pixpedia"))
return;
node.setAttribute("pixpedia", "true");
node.addEventListener("mouseover", this, true);
try {
const eTag = encodeURIComponent(node.textContent.trim());
if (!(eTag in this._existPixpedia))
this._existPixpedia[eTag] = !!await this.fetchJSON("https://www.pixiv.net/ajax/tag/" + eTag + "/info");
const a = document.createElement("a");
a.className = "pixpedia-icon" + (this._existPixpedia[eTag]? "": " pixpedia-icon-no-item");
a.href = "https://dic.pixiv.net/a/" + eTag;
node.parentElement.appendChild(a);
} catch (e) {
console.error(e);
}
},
handleEvent: function(event) {
event.stopPropagation();
},
authorTags: async function() {
this.replaceAuthorIcon();
const match = /illust_id=(\d+)/.exec(location.href);
if (!match)
return;
const illustId = match[1];
let authorId;
try {
if (!(illustId in this._illustTags))
this._illustTags[illustId] = await this.fetchJSON("https://www.pixiv.net/ajax/tags/illust/" + illustId);
const tagData = this._illustTags[illustId];
if (!tagData)
return;
authorId = tagData.authorId;
document.querySelectorAll("li._1tTPwGC").forEach(elem => {
let isOwn = false;
const a = elem.querySelector("a.gtm-new-work-tag-event-click");
if (a) {
const tag = a.textContent.trim();
const find = tagData.tags.find(t => t.tag == tag);
isOwn = find && find.userId === authorId;
}
if (isOwn)
elem.classList.add("author-tag-marker");
else
elem.classList.remove("author-tag-marker");
});
} catch (e) {
console.error(e);
}
if (this.enableTagCloud && authorId && this._currenAuthorId !== authorId) {
this._currenAuthorId = authorId;
this.authorTagCloud(authorId);
}
},
authorTagCloud: async function(authorId) {
const aside = document.querySelector("aside._2e0p8Qb");
if (!aside)
return;
let ok = false;
try {
// タグ一覧ページから引っ張ってきて差し込む
const tagAllUrl = "https://www.pixiv.net/member_tag_all.php?id=" + authorId;
const response = await this.fetchSameOrigin(tagAllUrl);
const text = await response.text();
const parser = new DOMParser();
const html = parser.parseFromString(text, "text/html");
const tagCloud = html.querySelector("ul.tagCloud");
if (tagCloud) {
let container = document.getElementById("author-tags");
if (!container) {
container = document.createElement("div");
container.id = "author-tags";
container.className = "_3mXmB-F";
aside.insertBefore(container, document.querySelector("._3M6FtEB"));
}
container.innerHTML = `<h2><a href="${tagAllUrl}">作品タグ</a></h2>`;
container.appendChild(tagCloud);
ok = true;
}
} catch (e) {
console.error(e);
}
if (!ok) {
const container = document.getElementById("author-tags");
if (container)
container.parentElement.removeChild(container);
}
},
replaceAuthorIcon: function() {
if (!this.enableReplaceAuthorIcon)
return;
const icon = document.querySelector("section.tYcZrl1 a._2lyPnMP");
if (icon) {
const img = icon.style.backgroundImage.replace("_50.", "_170.").replace("_s.", ".");
if (icon.style.backgroundImage !== img ) {
icon.style.backgroundImage = img;
icon.parentElement.classList.add("icon170");
}
}
},
fetchSameOrigin: function (url) {
return fetch(url, { mode: "same-origin", credentials: "same-origin" });
},
fetchJSON: async function(url) {
const response = await this.fetchSameOrigin(url);
const data = await response.json();
if (data.error)
throw new Error(data.message);
return data.body;
},
_style: `
/* 百科事典 */
.pixpedia-icon {
display: inline-block;
margin-left: 2px;
width: 15px;
height: 14px;
vertical-align: -2px;
text-decoration: none;
background: url(https://s.pximg.net/www/images/inline/pixpedia.png) no-repeat;
}
.pixpedia-icon-no-item {
background: url(https://s.pximg.net/www/images/inline/pixpedia-no-item.png) no-repeat;
}
.pixpedia-icon::before {
display: none;
}
/* 作者タグ */
.author-tag-marker::before {
content: "*" !important;
color: #E66;
}
/* "#"を消す */
.qE_sxIX::before {
display: none !important;
}
/* tag cloud */
#author-tags._3mXmB-F {
padding: 8px;
background-color: #FFF;
}
#author-tags h2 {
color: #333;
font-size: 14px;
margin: 0 0 8px;
}
#author-tags h2 a {
color: inherit;
text-decoration: none;
}
.tagCloud {
font-size: 12px;
line-height: 1.6;
padding: 0;
margin: 0;
word-break: break-all;
}
.tagCloud li {
display: inline;
font-size: 12px;
padding: 0px 2px;
margin: 0px;
}
.tagCloud li a {
color: inherit;
text-decoration: none;
}
.tagCloud li.level1 {
font-size: 20px;
font-weight: bold;
}
.tagCloud li.level1 a {
color: #3E5B71;
}
.tagCloud li.level2 {
font-size: 18px;
font-weight: bold;
}
.tagCloud li.level2 a {
color: #3E5B71;
}
.tagCloud li.level3 {
font-size: 17px;
font-weight: bold;
}
.tagCloud li.level3 a {
color: #587C97;
}
.tagCloud li.level4 {
font-size: 16px;
font-weight: bold;
}
.tagCloud li.level4 a {
color: #587C97;
}
.tagCloud li.level5 {
font-size: 14px;
font-weight: bold;
}
.tagCloud li.level5 a {
color: #587C97;
}
.tagCloud li.level6 a {
color: #5E9ECE;
}
.tagCloud li a:hover {
background-color: #3E5B71;
color: #FFF;
}
.tagCloud li .cnt {
font-size: 11px;
font-weight: normal;
color: #999999;
}
/* 作者アイコンを大きく */
section.tYcZrl1._3mXmB-F {
margin-top: 0;
}
.icon170._2kZnEk0 {
display: block !important;
text-align: center !important;
}
.icon170 a._2lyPnMP {
width: 170px !important;
height: 170px !important;
margin: 0 auto 4px !important;
border-radius: 4px !important;
background-position: center !important;
background-repeat: no-repeat !important;
background-size: contain !important;
}
`
};
pixivService.run();
})();