// ==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 作者アイコンを大サイズに差し替え // @downloadURL none // ==/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 = `