- // ==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/vue@3.4.38/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);