您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
pixiv.netで、非公開状態でブックマークするボタンを追加します
// ==UserScript== // @name PixivPrivateBookmarkButton // @namespace sgthr7/monkey-script // @version 0.0.1 // @author SGThr7 // @description pixiv.netで、非公開状態でブックマークするボタンを追加します // @description:en Add private bookmark button to pixiv.net // @license MIT // @match https://www.pixiv.net/* // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.global.prod.js // @grant GM_addStyle // ==/UserScript== (t=>{if(typeof GM_addStyle=="function"){GM_addStyle(t);return}const o=document.createElement("style");o.textContent=t,document.head.append(o)})(" .ppbb-root{display:inline;-webkit-user-select:none;user-select:none}.ppbb-main{padding-right:13px}.ppbb-absolute{position:absolute;bottom:0;right:32px}.private-bookmark-button[data-v-c5b4a471]{color:inherit;font-size:large;font-family:inherit}.container[data-v-c5b4a471]{position:relative}.heart[data-v-c5b4a471]{font-size:200%}.heart-fill[data-v-c5b4a471]{color:inherit}.heart-outline[data-v-c5b4a471]{position:absolute;right:0;bottom:0;color:#000}.bookmarked[data-v-c5b4a471]{color:#ff4060}.lock[data-v-c5b4a471]{font-size:100%;position:absolute;right:-5px;bottom:1px} "); (function (vue) { 'use strict'; const _withScopeId = (n) => (vue.pushScopeId("data-v-c5b4a471"), n = n(), vue.popScopeId(), n); const _hoisted_1 = { class: "container" }; const _hoisted_2 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("span", { class: "heart heart-outline" }, "♡", -1)); const _hoisted_3 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("span", { class: "lock" }, "🔒️", -1)); const _sfc_main = /* @__PURE__ */ vue.defineComponent({ __name: "PrivateBookmarkButton", props: { artworkId: { type: String, required: true, validator: (val) => { const validatorRegex = /^\d+$/; return validatorRegex.test(val); } }, relatedBookmarkButtonContainer: { type: Element, required: false } }, setup(__props) { const props = __props; const getBookmarkButton = () => { var _a; return (_a = props.relatedBookmarkButtonContainer) == null ? void 0 : _a.querySelector(":is(button, a:has(> svg))"); }; const isBookmarked = vue.ref(parseIsBookmarked()); function parseIsBookmarked() { var _a; const styleElementClass = "sc-j89e3c-1"; const styleElement = (_a = props.relatedBookmarkButtonContainer) == null ? void 0 : _a.querySelector(`.${styleElementClass}`); const bookmarkedClassName = "bXjFLc"; return (styleElement == null ? void 0 : styleElement.classList.contains(bookmarkedClassName)) ?? false; } if (props.relatedBookmarkButtonContainer != null) { const observer = new MutationObserver(() => { isBookmarked.value = parseIsBookmarked(); }); observer.observe(props.relatedBookmarkButtonContainer, { subtree: true, childList: true, attributes: true, attributeFilter: ["class"] }); } const bookmarkPageUrl = vue.computed(() => new URL(`https://www.pixiv.net/bookmark_add.php?type=illust&illust_id=${props.artworkId}`)); function privateBookmark() { var _a; (_a = getBookmarkButton()) == null ? void 0 : _a.click(); if (isBookmarked.value) { return; } const bookmarkPageWindow = window.open(bookmarkPageUrl.value, "_blank", "popup,width=1,height=1,top=0,left=0"); const bookmarkPageAction = () => { if (bookmarkPageWindow == null) { throw new Error("Failed to get bookmark page window"); } const bookmarkPageDocument = bookmarkPageWindow.document; if (bookmarkPageDocument == null) { throw new Error("Failed to get bookmark page document"); } const form = bookmarkPageDocument.querySelector("section.bookmark-detail-unit>form"); if (form == null) { throw new Error("Failed to find bookmark form"); } const restrictRadio = form.elements.namedItem("restrict"); if (restrictRadio == null || !isRadioNodeList(restrictRadio)) { throw new Error("Failed to get restrict radio button"); } restrictRadio.value = "1"; const finishedEventName = "pagehide"; const onBookmarkedAction = () => { bookmarkPageWindow.removeEventListener(finishedEventName, onBookmarkedAction); bookmarkPageWindow.close(); }; bookmarkPageWindow.addEventListener(finishedEventName, onBookmarkedAction); form.requestSubmit(); }; bookmarkPageWindow == null ? void 0 : bookmarkPageWindow.addEventListener("load", bookmarkPageAction); } function isRadioNodeList(target) { return target instanceof RadioNodeList || target.toString() === RadioNodeList.prototype.toString(); } return (_ctx, _cache) => { return vue.openBlock(), vue.createElementBlock("button", { type: "button", class: "ppbb-button fgVkZi", onClick: privateBookmark }, [ vue.createElementVNode("div", _hoisted_1, [ vue.createElementVNode("span", { class: vue.normalizeClass(["heart heart-fill", { bookmarked: isBookmarked.value }]) }, "♥", 2), _hoisted_2, vue.createTextVNode("️"), _hoisted_3 ]) ]); }; } }); const _export_sfc = (sfc, props) => { const target = sfc.__vccOpts || sfc; for (const [key, val] of props) { target[key] = val; } return target; }; const PrivateBookmarkButton = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-c5b4a471"]]); function isElement(node) { return node.nodeType === Node.ELEMENT_NODE; } const globalObserver = new MutationObserver((records, _observer) => { records.forEach((record) => { if (record.addedNodes.length <= 0) { return; } if (Array.from(record.addedNodes).some((node) => isElement(node) && Array.from(node.classList).some((className) => className.startsWith("ppbb")))) { return; } Array.from(record.addedNodes).filter(isElement).filter( (el) => el.querySelectorAll("button.sc-kgq5hw-0").length === 1 && el.querySelector("div.ppbb-root") == null ).forEach(applyThumbnailArtwork); if (record.addedNodes.length === 1) { const maybeContainersOwner = record.addedNodes[0]; if (isElement(maybeContainersOwner)) { const artworkContainersList = maybeContainersOwner.querySelectorAll(":is(ul, div.sc-1nhgff6-4) > :is(div, li):has(button.sc-kgq5hw-0)"); artworkContainersList.forEach((artworkContainers) => { Array.from(artworkContainers.children).filter((el) => el.querySelector("div.ppbb-root") == null).forEach(applyThumbnailArtwork); }); } } }); }); const globalObserverOption = { childList: true, subtree: true }; function init() { const initialArtworkContainers = document.querySelectorAll("div:has(a[data-gtm-value]):has(div:nth-child(2) button.sc-kgq5hw-0)"); initialArtworkContainers.forEach((el) => { if (el.querySelectorAll("button.sc-kgq5hw-0").length === 1 && el.querySelector("div.ppbb-root") == null) { applyThumbnailArtwork(el); } }); window.addEventListener("load", onLoad); globalObserver.observe(document, globalObserverOption); const titleObserver = new MutationObserver((records, _observer) => { initMainArtwork(); }); const title = document.head.querySelector("title"); if (title != null) { titleObserver.observe(title, { childList: true, subtree: true }); } } function onLoad() { initMainArtwork(); } init(); function initMainArtwork() { var _a; const buttonContainer = document.querySelector("div.sc-181ts2x-3"); if (buttonContainer == null) { return; } const url = new URL(window.location.href); const artworkPageRegex = /^\/(?:en\/)?artworks\/(\d+)$/; const regexResult = url.pathname.match(artworkPageRegex); if (regexResult == null || regexResult.length <= 1) { return; } const artworkId = regexResult[1]; const ppbbRoot = document.createElement("div"); ppbbRoot.classList.add("ppbb-root", "ppbb-main"); (_a = buttonContainer.parentNode) == null ? void 0 : _a.insertBefore(ppbbRoot, buttonContainer.nextElementSibling); const app = vue.createApp(PrivateBookmarkButton, { artworkId, relatedBookmarkButtonContainer: buttonContainer }); app.mount(ppbbRoot); } function applyThumbnailArtwork(target) { var _a; const artworkLink = target.querySelector("a[data-gtm-value]"); if (artworkLink == null) { return; } const artworkId = artworkLink.getAttribute("data-gtm-value"); if (artworkId == null) { return; } const button = target.querySelector("button"); if (button == null) { return; } const buttonContainer = (_a = button.parentElement) == null ? void 0 : _a.parentElement; if (buttonContainer == null) { return; } const ppbbRoot = document.createElement("div"); ppbbRoot.classList.add("ppbb-root", "ppbb-absolute"); buttonContainer.appendChild(ppbbRoot); const app = vue.createApp(PrivateBookmarkButton, { artworkId, relatedBookmarkButtonContainer: button.parentElement }); app.mount(ppbbRoot); } })(Vue);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址