Greasy Fork

来自缓存

Greasy Fork is available in English.

孔夫子旧书网图片下载(自动去水印)

批量下载孔夫子旧书网图片,并自动去水印

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         孔夫子旧书网图片下载(自动去水印)
// @description  批量下载孔夫子旧书网图片,并自动去水印
// @version      4.2
// @author       路人甲乙丙
// @namespace    iblogc
// @match        *://search.kongfz.com/*
// @match        *://book.kongfz.com/*
// @match        *://item.kongfz.com/*
// @match        *://book.kongfz.com/C*
// @grant        GM_addStyle
// @grant        GM_download
// @grant        GM_xmlhttpRequest
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @license      Apache License, Version 2.0
// @require      https://cdn.jsdelivr.net/npm/[email protected]/runtime.min.js
// @homepage     http://greasyfork.icu/zh-CN/scripts/467062
// ==/UserScript==

"use strict";function _asyncToGenerator(n){return function(){var e=n.apply(this,arguments);return new Promise(function(n,t){function o(r,a){try{var i=e[r](a),s=i.value}catch(n){return void t(n)}if(!i.done)return Promise.resolve(s).then(function(n){o("next",n)},function(n){o("throw",n)});n(s)}return o("next")})}}!function(){function n(){var n=Object.values(R),t=n.indexOf(T),r=(t+1)%n.length,a=n[r];if(a===R.CUSTOM_WATERMARK&&!q)return alert("请先在设置面板中上传自定义水印图片"),void o();T=a,GM_setValue("watermarkRemovalMethod",a),alert("已切换为"+e(a)+"方式")}function e(n){switch(n){case R.CANVAS_COVER:return"纯色覆盖";case R.CUSTOM_WATERMARK:return"自定义水印";case R.CROP_BOTTOM:return"裁剪底部";default:return"未设置"}}function t(){var n=document.createElement("div");return n.className="settings-panel",n.innerHTML='\n      <div class="settings-header">\n        <h3>去水印备选方案设置</h3>\n        <button class="close-button">×</button>\n      </div>\n      <div class="settings-content">\n        <div class="settings-notice">\n          <div class="notice-icon">ⓘ</div>\n          <div class="notice-text">\n            系统会优先使用完美去水印方式,\n            仅在该方式失效时(目前失效率很高)才会使用以下备选方案。\n          </div>\n        </div>\n\n        <div class="settings-section">\n          <div class="method-options">\n            <label class="method-radio">\n              <input type="radio" name="watermarkMethod" value="canvas_cover" \n                     '+(T===R.CANVAS_COVER?"checked":"")+'>\n              <div class="method-radio-content">\n                <span class="method-title">纯色覆盖</span>\n                <span class="method-desc">采集图片右下角的颜色,用相近的颜色覆盖水印区域,适合底色均匀的图片。</span>\n              </div>\n            </label>\n            <label class="method-radio">\n              <input type="radio" name="watermarkMethod" value="custom_watermark"\n                     '+(T===R.CUSTOM_WATERMARK?"checked":"")+'>\n              <div class="method-radio-content">\n                <span class="method-title">自定义水印</span>\n                <span class="method-desc">使用自定义图片覆盖水印区域,可以上传自己设计的水印或纯色图片。</span>\n              </div>\n            </label>\n            <label class="method-radio">\n              <input type="radio" name="watermarkMethod" value="crop_bottom"\n                     '+(T===R.CROP_BOTTOM?"checked":"")+'>\n              <div class="method-radio-content">\n                <span class="method-title">裁剪底部</span>\n                <span class="method-desc">直接裁剪掉图片底部的水印区域,适合水印区域内容不重要的图片。</span>\n              </div>\n            </label>\n          </div>\n        </div>\n\n        <div id="customWatermarkSection" class="settings-section" \n             style="display: '+(T===R.CUSTOM_WATERMARK?"block":"none")+'">\n          <h4>自定义水印图片</h4>\n          <span class="method-desc">\n            脚本会自动缩放水印图片,以适应水印区域,并且保持水印图片比例,宽:高=5:2的图片刚好能覆盖水印区域。\n            当然你也可以上传其它比例图片,不管怎样的水印图片,脚本都会自动缩放以覆盖水印区域。\n          </span>\n          <div class="file-upload">\n            <label class="file-upload-button" for="watermarkFile">\n              选择水印图片\n            </label>\n            <input type="file" id="watermarkFile" accept="image/*">\n          </div>\n          '+(q?'<div class="preview-wrapper">\n               <img src="'+q+'" class="preview-image">\n             </div>':"")+'\n        </div>\n      </div>\n      <div class="settings-footer">\n        <button id="saveSettings" class="save-button">保存设置</button>\n        <div class="settings-footer-links">\n          <a href="#" id="donation" style="color: #007bff; text-decoration: none;">\n            💰 赞赏支持\n          </a>\n          <span class="link-separator">|</span>\n          <a href="#" id="devService" style="color: #007bff; text-decoration: none;">\n            💻 软件/脚本/自动化定制开发\n          </a>\n        </div>\n      </div>\n    ',n}function o(){var n=document.createElement("div");n.className="settings-overlay",document.body.appendChild(n);var e=t();document.body.appendChild(e),e.querySelectorAll('input[name="watermarkMethod"]').forEach(function(n){n.addEventListener("change",function(){e.querySelector("#customWatermarkSection").style.display=n.value===R.CUSTOM_WATERMARK?"block":"none"})}),e.querySelector("#saveSettings").onclick=function(){var t=e.querySelector('input[name="watermarkMethod"]:checked').value;T=t,GM_setValue("watermarkRemovalMethod",t),GM_setValue("customWatermarkBase64",q),alert("设置已保存"),e.remove(),n.remove()},e.querySelector(".close-button").onclick=function(){e.remove(),n.remove()},e.querySelector("#watermarkFile").onchange=function(n){var t=n.target.files[0];if(t){var o=new FileReader;o.onload=function(n){q=n.target.result;var t=e.querySelector(".preview-image");if(t)t.src=q;else{var o=document.createElement("div");o.className="preview-wrapper";var r=document.createElement("img");r.src=q,r.className="preview-image",o.appendChild(r),e.querySelector(".file-upload").insertAdjacentElement("afterend",o)}},o.readAsDataURL(t)}},e.querySelector("#devService").addEventListener("click",function(n){n.preventDefault(),z()}),e.querySelector("#donation").addEventListener("click",function(n){n.preventDefault(),g()})}function r(n){B=n,localStorage.setItem(A,n)}function a(){D=!0,localStorage.setItem(O,"true")}function i(n){return n.replace(/(_water|_n|_p|_b|_s)/g,"")}function s(n,e){var t=n.createElement("button");t.innerText="👉 下载图片",t.className="searchPageDownloadButton item-button",t.style.backgroundColor="#8c222c",t.style.color="white";var o=e.querySelector("div.add-cart-btn")||e.querySelector("div.add-cart-button");return o.parentNode.insertBefore(t,o.nextSibling),t}function c(n,e){var t=n.createElement("button");t.innerText="👉 下载图片",t.className="searchPageDownloadButton item-button",t.style.backgroundColor="#8c222c",t.style.color="white";var o=e.querySelector("div.add-cart-btn")||e.querySelector("div.add-cart-button");return o.parentNode.insertBefore(t,o.nextSibling),t}function d(n,e){var t=n.createElement("button");t.innerText="👉 下载图片",t.className="bookListPageDownloadButton",t.style.backgroundColor="#8c222c",t.style.color="white";var o=e.querySelector("a.con-btn-cart");return o.parentNode.insertBefore(t,o.nextSibling),t}function l(n,e){u(n,e)}function p(n){var e=n.querySelectorAll("ul#figure-info-box > li");return Array.from(e,function(n){return n.querySelector("img").getAttribute("_viewsrc")})}function u(n,e){function t(){e.style.lineHeight="20px",e.innerText="📢总计:"+o.length+"\n✨完美去水印:"+s+"\n🎨备选去水印:"+c+"\n🔄未去水印:"+d+"\n😭下载失败:"+l+"\n",e.appendChild(a),l>0?(e.style.backgroundColor="#c97c75",e.style.color="#fff"):(e.style.backgroundColor="#7b7475",e.style.color="#fff")}var o=p(n);e.style.cursor="not-allowed";var a=document.createElement("a");if(a.href="#",a.textContent="🐛问题反馈",a.style.color="#ffeb83",a.onclick=function(n){n.preventDefault(),f("https://greasyfork.s3.us-east-2.amazonaws.com/lp9hdyffstt0wpz2ub39gw9p6srr")},0===o.length)return e.innerText="🧐商品详情中没\n有图片可以下载\n",e.style.backgroundColor="#ccc",e.style.color="#999",a.style.color="#b55222",void e.appendChild(a);e.disabled=!0,e.innerText="Downloading...";var s=0,c=0,d=0,l=0,u=(n.querySelector('meta[name="keywords"]').getAttribute("content")||"").match(/([^,]+)/),m=u&&u.length>1?u[1]:"",h=(n.querySelector('meta[name="description"]').getAttribute("content")||"").match(/ISBN:([0-9]*)/),x=h&&h.length>1?h[1]:"";o.forEach(function(n,a){function p(i){var u=this,h=arguments.length>1&&void 0!==arguments[1]&&arguments[1],v=arguments.length>2&&void 0!==arguments[2]&&arguments[2],b=v?"original":h?T:"direct",y=C(a,m,x,f,b);console.log("开始下载图片:",{url:i,filename:y,isRetry:h,isOriginal:v,currentProgress:s+c+d+l+1+"/"+o.length}),GM_download({url:i,name:y,onprogress:function(n){e.innerText="Downloading...("+(a+1)+"/"+o.length+")"},onload:function(){v?(d++,console.log("原图下载成功 - 总进度: "+(s+c+d+l)+"/"+o.length)):h?(c++,console.log("Canvas处理图片下载成功 - 总进度: "+(s+c+d+l)+"/"+o.length)):(s++,console.log("直接去水印下载成功 - 总进度: "+(s+c+d+l)+"/"+o.length)),s+c+d+l===o.length&&(console.log("所有图片处理完成:",{"直接去水印成功":s,"Canvas处理成功":c,"原图下载":d,"失败":l}),t(),r(B+s+c+d),(B%100==0&&0!==B&&!D||B>1e3&&!D)&&g())},onerror:function(){var e=_asyncToGenerator(regeneratorRuntime.mark(function e(r){var a;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(h||v){e.next=15;break}return console.log("无水印链接下载失败,尝试Canvas处理...",r),e.prev=2,e.next=5,M(n);case 5:a=e.sent,p(a,!0,!1),e.next=13;break;case 9:e.prev=9,e.t0=e.catch(2),console.log("Canvas处理失败,降级到原图下载:",e.t0),p(n,!0,!0);case 13:e.next=16;break;case 15:h&&!v?(console.log("Canvas处理图片下载失败,降级到原图下载:",r),p(n,!0,!0)):(l++,console.error("图片下载完全失败:",r),s+c+d+l===o.length&&t());case 16:case"end":return e.stop()}},e,u,[[2,9]])}));return function(n){return e.apply(this,arguments)}}()})}var u=i(n),f=(u.split(".").pop()||"").toLowerCase();m.trim(),x.trim();p(u)})}function g(){k();var n=document.createElement("div");n.classList.add("overlay"),document.body.appendChild(n);var e=document.createElement("div");e.classList.add("donation-popup"),e.innerHTML='\n      <div class="donation-header">\n        <h3>孔夫子旧书网图片下载(自动去水印)</h3>\n        <button class="close-button">×</button>\n        <p style="font-size: 14px; color: #666;">让您的时间更高效</p>\n      </div>\n      <div class="donation-body">\n        <p>🙏感谢您选择此工具!捐赠是对我最大的支持,也能帮助工具不断改进与维护。</p>\n        <div class="donation-images">\n          <img src="https://greasyfork.s3.us-east-2.amazonaws.com/hve4r1x61p2vrsx2bjqjb1um8wfh" alt="捐赠二维码1" class="donation-image-large" />\n          <img src="https://greasyfork.s3.us-east-2.amazonaws.com/2w21qpqvqb9iikjqiovagnuyut1x" alt="捐赠二维码2" class="donation-image-large" />\n        </div>\n        <div class="donation-links">\n          <a href="#" id="feedbackWeChat">\n            ❓问题/建议反馈微信:Byte4Me\n          </a>\n          <a href="#" id="sideHustleGroup">\n            💰副业社群体检卡\n          </a>\n          <a href="#" id="devService">\n            💻 软件/脚本/自动化定制开发\n          </a>\n        </div>\n         <div class="donation-footer">\n            <button id="donateBtn" class="donation-button donate">我已捐赠💖</button>\n        </div>\n      </div>\n    ',document.body.appendChild(e);var t=e.querySelector(".close-button");e.querySelector("#donateBtn").addEventListener("click",function(){alert("🙏感谢您的支持!如果有问题,欢迎联系微信:Byte4Me"),e.remove(),n.remove(),a()}),t.addEventListener("click",function(){e.remove(),n.remove()}),e.querySelector("#feedbackWeChat").addEventListener("click",function(n){n.preventDefault(),f("https://greasyfork.s3.us-east-2.amazonaws.com/lp9hdyffstt0wpz2ub39gw9p6srr")}),e.querySelector("#sideHustleGroup").addEventListener("click",function(n){n.preventDefault(),f("https://greasyfork.s3.us-east-2.amazonaws.com/7cjf1r8rohkrh8xwp0mn2srocx0u")}),e.querySelector("#devService").addEventListener("click",function(n){n.preventDefault(),z()})}function f(n){var e=document.createElement("div"),t=document.createElement("div");t.classList.add("image-popup"),t.innerHTML='\n      <div class="image-popup-header">\n        <button class="close-button">×</button>\n      </div>\n      <div class="image-popup-body">\n        <img src="'+n+'" alt="Image" />\n      </div>\n    ',document.body.appendChild(t),t.querySelector(".close-button").addEventListener("click",function(){t.remove(),e.remove()}),e.addEventListener("click",function(){t.remove(),e.remove()})}function m(n,e){e.addEventListener("click",function(){GM_xmlhttpRequest({method:"GET",url:n,onload:function(n){u((new DOMParser).parseFromString(n.responseText,"text/html"),e)},onerror:function(n){console.log("Error:",n),e.innerText="⛔ 解析网页时出错"}})})}function h(n){m(n.querySelector(".item-info-box > .item-name > a.item-link").href,s(document,n))}function x(n){m(n.querySelector(".item-info > .title > a.link").href,c(document,n))}function v(n){m(n.querySelector("div.list-con-title > a").href,d(document,n))}function b(){document.querySelector(".product-item-box")&&(clearInterval(N),document.querySelectorAll(".product-item-box > .product-item-wrap").forEach(function(n){h(n)}))}function y(){document.querySelector("#listBox")&&(clearInterval(N),document.querySelectorAll("#listBox > .item").forEach(function(n){x(n)}))}function w(){document.querySelector("ul.itemList")&&(clearInterval(N),document.querySelectorAll("ul.itemList > li").forEach(function(n){v(n)}))}function k(){var n=document.createElement("div");n.className="confetti-container",document.body.appendChild(n);for(var e=0;e<50;e++){var t=document.createElement("div");t.className="confetti",t.style.left=100*Math.random()+"vw",t.style.animationDelay=3*Math.random()+"s",t.style.backgroundColor="hsl("+360*Math.random()+", 100%, 50%)",n.appendChild(t)}setTimeout(function(){n.remove()},5e3)}function C(n,e,t,o,r){var a=void 0;switch(r){case"direct":a="完美去水印";break;case R.CANVAS_COVER:a="纯色覆盖";break;case R.CUSTOM_WATERMARK:a="自定义水印";break;case R.CROP_BOTTOM:a="裁剪底部";break;default:a="未知方式"}return a+"_"+e.trim()+"-"+t.trim()+"-"+(n+1)+"."+(o||"jpg")}function S(n){var e=this,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],o=arguments.length>2&&void 0!==arguments[2]&&arguments[2],a=o?"original":t?T:"direct",i=C(index,bookName,isbn,extension,a);console.log("开始下载图片:",{url:n,filename:i,isRetry:t,isOriginal:o,currentProgress:directSuccessCount+canvasSuccessCount+originalImageCount+failCount+1+"/"+images.length}),GM_download({url:n,name:i,onprogress:function(n){downloadButton.innerText="Downloading...("+(index+1)+"/"+images.length+")"},onload:function(){o?(originalImageCount++,console.log("原图下载成功 - 总进度: "+(directSuccessCount+canvasSuccessCount+originalImageCount+failCount)+"/"+images.length)):t?(canvasSuccessCount++,console.log("Canvas处理图片下载成功 - 总进度: "+(directSuccessCount+canvasSuccessCount+originalImageCount+failCount)+"/"+images.length)):(directSuccessCount++,console.log("直接去水印下载成功 - 总进度: "+(directSuccessCount+canvasSuccessCount+originalImageCount+failCount)+"/"+images.length)),directSuccessCount+canvasSuccessCount+originalImageCount+failCount===images.length&&(console.log("所有图片处理完成:",{"直接去水印成功":directSuccessCount,"Canvas处理成功":canvasSuccessCount,"原图下载":originalImageCount,"失败":failCount}),updateDownloadButton(),r(B+directSuccessCount+canvasSuccessCount+originalImageCount),(B%100==0&&0!==B&&!D||B>1e3&&!D)&&g())},onerror:function(){var n=_asyncToGenerator(regeneratorRuntime.mark(function n(r){var a;return regeneratorRuntime.wrap(function(n){for(;;)switch(n.prev=n.next){case 0:if(t||o){n.next=15;break}return console.log("无水印链接下载失败,尝试Canvas处理...",r),n.prev=2,n.next=5,M(imageUrl);case 5:a=n.sent,S(a,!0,!1),n.next=13;break;case 9:n.prev=9,n.t0=n.catch(2),console.log("Canvas处理失败,降级到原图下载:",n.t0),S(imageUrl,!0,!0);case 13:n.next=16;break;case 15:t&&!o?(console.log("Canvas处理图片下载失败,降级到原图下载:",r),S(imageUrl,!0,!0)):(failCount++,console.error("图片下载完全失败:",r),directSuccessCount+canvasSuccessCount+originalImageCount+failCount===images.length&&updateDownloadButton());case 16:case"end":return n.stop()}},n,e,[[2,9]])}));return function(e){return n.apply(this,arguments)}}()})}function z(){var n=document.createElement("div");n.className="overlay",n.style.zIndex="10003",document.body.appendChild(n);var e=document.createElement("div");e.className="dev-service-popup",e.innerHTML='\n      <div class="dev-service-header">\n        <h3>专业软件定制开发服务</h3>\n        <button class="close-button">×</button>\n      </div>\n      <div class="dev-service-body">\n        <div class="service-sections">\n          <div class="service-intro">\n            <h4>🌟 服务范围</h4>\n            <ul>\n              <li>浏览器脚本工具开发</li>\n              <li>数据采集爬虫开发</li>\n              <li>RPA自动化流程开发</li>\n              <li>网站建设与软件小程序开发</li>\n              <li>其他定制化开发需求</li>\n            </ul>\n          </div>\n          <div class="service-intro">\n            <h4>💪 为什么选择我们</h4>\n            <ul>\n              <li>专业技术团队,经验丰富</li>\n              <li>一对一需求对接,快速响应</li>\n              <li>合理报价,质量保证</li>\n              <li>交付及时,售后无忧</li>\n            </ul>\n          </div>\n        </div>\n        <div class="contact-info">\n          <div class="contact-qr">\n            <img src="https://greasyfork.s3.us-east-2.amazonaws.com/lp9hdyffstt0wpz2ub39gw9p6srr" alt="联系方式">\n            <p>微信号: Byte4Me</p>\n          </div>\n          <p class="contact-note">扫码或添加微信咨询</p>\n        </div>\n      </div>\n    ',document.body.appendChild(e),e.querySelector(".close-button").onclick=function(){e.remove(),n.remove()},n.onclick=function(){e.remove(),n.remove()}}var M=function(){var n=_asyncToGenerator(regeneratorRuntime.mark(function n(e){return regeneratorRuntime.wrap(function(n){for(;;)switch(n.prev=n.next){case 0:return console.log("开始Canvas处理水印,原图URL:",e),n.abrupt("return",new Promise(function(n,t){var o=new Image;o.crossOrigin="anonymous",o.onload=_asyncToGenerator(regeneratorRuntime.mark(function e(){var r,a;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:console.log("图片加载成功,尺寸:",o.width,"x",o.height),r=document.createElement("canvas"),a=r.getContext("2d"),e.t0=T,e.next=e.t0===R.CANVAS_COVER?6:e.t0===R.CUSTOM_WATERMARK?12:e.t0===R.CROP_BOTTOM?18:22;break;case 6:return r.width=o.width,r.height=o.height,a.drawImage(o,0,0),e.next=11,E(a,o);case 11:return e.abrupt("break",22);case 12:return r.width=o.width,r.height=o.height,a.drawImage(o,0,0),e.next=17,_(a,o);case 17:return e.abrupt("break",22);case 18:return r.width=o.width,r.height=o.height-o.width/10,a.drawImage(o,0,0),e.abrupt("break",22);case 22:r.toBlob(function(e){if(e){var o=URL.createObjectURL(e);console.log("Canvas处理完成,生成新URL:",o),n(o)}else console.error("Canvas转Blob失败"),t(new Error("Canvas to Blob conversion failed"))},"image/jpeg",.95);case 23:case"end":return e.stop()}},e,this)})),o.onerror=function(n){console.error("图片加载失败:",n),t(new Error("Image loading failed"))},o.src=e}));case 2:case"end":return n.stop()}},n,this)}));return function(e){return n.apply(this,arguments)}}(),E=function(){var n=_asyncToGenerator(regeneratorRuntime.mark(function n(e,t){var o,r,a,i,s,c,d,l,p,u,g,f,m,h,x,v,b,y;return regeneratorRuntime.wrap(function(n){for(;;)switch(n.prev=n.next){case 0:for(o=t.width/4,r=t.width/10,a=t.width-o,i=t.height-r,s=5,c=0,d=0,l=0,p=0,u=a+o-s;u<a+o;u++)for(g=i+r-s;g<i+r;g++)f=e.getImageData(u,g,1,1).data,c+=f[0],d+=f[1],l+=f[2],p++;for(m=Math.round(c/p),h=Math.round(d/p),x=Math.round(l/p),v=e.getImageData(a,i,o,r),b=v.data,y=0;y<b.length;y+=4)b[y]=m+10*(Math.random()-.5),b[y+1]=h+10*(Math.random()-.5),b[y+2]=x+10*(Math.random()-.5),b[y+3]=245;e.putImageData(v,a,i),e.filter="blur(2px)",e.fillStyle="rgba("+m+", "+h+", "+x+", 0.3)",e.fillRect(a,i,o,r),e.filter="none";case 18:case"end":return n.stop()}},n,this)}));return function(e,t){return n.apply(this,arguments)}}(),_=function(){var n=_asyncToGenerator(regeneratorRuntime.mark(function n(e,t){return regeneratorRuntime.wrap(function(n){for(;;)switch(n.prev=n.next){case 0:if(q){n.next=2;break}throw new Error("未设置自定义水印图片");case 2:return n.abrupt("return",new Promise(function(n,o){var r=new Image;r.crossOrigin="anonymous",r.onload=function(){var o=t.width/4,a=t.width/10,i=r.width/r.height,s=o/a,c=void 0,d=void 0,l=void 0,p=void 0;i>s?(d=a,c=d*i,p=t.height-a,l=t.width-c+(c-o)/2):(c=o,d=c/i,l=t.width-o,p=t.height-d+(d-a)/2),e.drawImage(r,l,p,c,d),n()},r.onerror=function(){o(new Error("自定义水印图片加载失败"))},r.src=q}));case 3:case"end":return n.stop()}},n,this)}));return function(e,t){return n.apply(this,arguments)}}(),R={CANVAS_COVER:"canvas_cover",CUSTOM_WATERMARK:"custom_watermark",CROP_BOTTOM:"crop_bottom"},T=GM_getValue("watermarkRemovalMethod",R.CANVAS_COVER),q=GM_getValue("customWatermarkBase64","");GM_getValue("cropRatio",.9);GM_registerMenuCommand("⚙️ 去水印设置",o),GM_registerMenuCommand("✨ 当前方式:"+e(T),n),GM_addStyle('\n    .settings-overlay {\n      position: fixed;\n      top: 0;\n      left: 0;\n      width: 100%;\n      height: 100%;\n      background: rgba(0, 0, 0, 0.3);\n      backdrop-filter: blur(5px);\n      z-index: 9998;\n    }\n\n    .settings-panel {\n      position: fixed;\n      top: 50%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      background: rgba(255, 255, 255, 0.95);\n      padding: 32px;\n      border-radius: 16px;\n      box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);\n      z-index: 9999;\n      width: 800px;\n      max-height: 90vh;\n      overflow-y: auto;\n      scrollbar-width: none;\n    }\n\n    .settings-panel::-webkit-scrollbar {\n      display: none;\n    }\n\n    .settings-header {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      margin-bottom: 24px;\n      position: relative;\n    }\n\n    .settings-header h3 {\n      font-size: 20px;\n      font-weight: 600;\n      color: #1d1d1f;\n      margin: 0;\n    }\n\n    .settings-notice {\n      display: flex;\n      align-items: flex-start;\n      background: #f5f5f7;\n      border-radius: 12px;\n      padding: 16px;\n      margin-bottom: 24px;\n    }\n\n    .notice-icon {\n      font-size: 20px;\n      color: #06c;\n      margin-right: 12px;\n    }\n\n    .notice-text {\n      font-size: 14px;\n      line-height: 1.4;\n      color: #1d1d1f;\n    }\n\n    .settings-section {\n      margin-bottom: 24px;\n    }\n\n    .settings-section h4 {\n      font-size: 16px;\n      font-weight: 600;\n      color: #1d1d1f;\n      margin: 0 0 5px 0;\n    }\n\n    .size-inputs {\n      display: flex;\n      align-items: center;\n      gap: 12px;\n      margin-top: 12px;\n      justify-content: center;\n    }\n\n    .size-input-wrapper {\n      display: flex;\n      align-items: center;\n      gap: 8px;\n      flex: 0 1 auto;\n    }\n\n    .size-input-wrapper label {\n      white-space: nowrap;\n      color: #86868b;\n      font-size: 13px;\n    }\n\n    .input-unit-wrapper {\n      position: relative;\n      display: flex;\n      align-items: center;\n      min-width: 120px;\n    }\n\n    .size-separator {\n      margin: 0 8px;\n      color: #86868b;\n      font-size: 14px;\n      line-height: 1;\n    }\n\n    input[type="text"] {\n      width: 100%;\n      padding: 8px 50px 8px 12px;\n      border: 1px solid #d2d2d7;\n      border-radius: 8px;\n      font-size: 14px;\n      color: #1d1d1f;\n    }\n\n    .unit-select {\n      position: absolute;\n      right: 8px;\n      top: 50%;\n      transform: translateY(-50%);\n      border: none;\n      background: transparent;\n      font-size: 14px;\n      color: #86868b;\n      cursor: pointer;\n      padding-right: 16px;\n    }\n\n    .method-options {\n      display: flex;\n      gap: 16px;\n      margin-bottom: 24px;\n    }\n\n    .method-radio {\n      flex: 1;\n      cursor: pointer;\n    }\n\n    .method-radio input[type="radio"] {\n      display: none;\n    }\n\n    .method-radio-content {\n      padding: 16px;\n      background: #f8f9fa;\n      border: 1px solid #dee2e6;\n      border-radius: 12px;\n      text-align: center;\n      transition: all 0.2s;\n    }\n\n    .method-radio input[type="radio"]:checked + .method-radio-content {\n      background: #e8f2ff;\n      border: 1px solid #06c;\n    }\n\n    .method-title {\n      display: block;\n      font-size: 15px;\n      font-weight: 600;\n      color: #1d1d1f;\n      margin-bottom: 12px;\n      padding-bottom: 8px;\n      border-bottom: 1px solid #eee;\n    }\n\n    .method-desc {\n      display: block;\n      font-size: 13px;\n      line-height: 1.5;\n      color: #666;\n      text-align: left;\n      padding: 0 4px;\n    }\n\n    .preview-wrapper {\n      margin: 16px auto;\n      border-radius: 8px;\n      overflow: hidden;\n      border: 1px solid #d2d2d7;\n      max-width: 200px !important;  \n      max-height: 80px !important;  \n      width: 200px;\n      height: 80px;\n      background: #f5f5f7;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n    }\n\n    .preview-image {\n      width: 100%;\n      height: 100%;\n      object-fit: contain; // 保持图片比例,确保完整显示\n    }\n\n    .crop-mode .size-input-wrapper {\n      max-width: 300px;\n      margin: 0 auto;\n    }\n\n    .file-upload {\n      margin-bottom: 16px;\n      text-align: center;\n    }\n\n    .file-upload-button {\n      display: inline-block;\n      padding: 8px 16px;\n      background: #06c;\n      color: white;\n      border-radius: 8px;\n      font-size: 14px;\n      cursor: pointer;\n      transition: background-color 0.2s;\n    }\n\n    .file-upload-button:hover {\n      background: #0055b3;\n    }\n\n    .file-upload input[type="file"] {\n      display: none;\n    }\n\n    .close-button {\n      width: 28px;\n      height: 28px;\n      border: none;\n      background: #f5f5f7;\n      border-radius: 50%;\n      font-size: 18px;\n      color: #86868b;\n      cursor: pointer;\n      transition: all 0.2s;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n    }\n\n    .close-button:hover {\n      background: #e5e5e7;\n      color: #1d1d1f;\n    }\n\n    .settings-footer {\n      margin-top: 24px;\n      text-align: center;\n    }\n\n    .save-button {\n      padding: 10px 24px;\n      background: #06c;\n      color: white;\n      border: none;\n      border-radius: 8px;\n      font-size: 15px;\n      font-weight: 500;\n      cursor: pointer;\n      transition: background-color 0.2s;\n    }\n\n    .save-button:hover {\n      background: #0055b3;\n    }\n\n    /* 图片弹窗样式 */\n    .image-popup {\n      position: fixed;\n      top: 50%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      background: white;\n      border-radius: 16px;\n      box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);\n      z-index: 10004;\n      overflow: hidden;\n    }\n\n    .image-popup-header {\n      position: relative;\n      height: 0;\n    }\n\n    .image-popup-body {\n      padding: 30px;\n    }\n\n    .image-popup img {\n      max-width: 700px;\n      max-height: 80vh;\n      border-radius: 8px;\n      display: block;\n    }\n\n    /* 设置面板底部链接样式 */\n    .settings-footer-links {\n      margin-top: 15px;\n      text-align: center;\n    }\n\n    .link-separator {\n      margin: 0 10px;\n      color: #dee2e6;\n    }\n\n    /* 捐赠弹窗样式优化 */\n    .donation-popup {\n      max-width: 800px;\n      width: 90%;\n      padding: 30px;\n    }\n\n    .donation-header {\n      position: relative;\n      text-align: center;\n      margin-bottom: 25px;\n      padding-bottom: 15px;\n      border-bottom: 2px solid #f0f2f5;\n    }\n\n    .donation-header h3 {\n      margin: 0;\n      font-size: 24px;\n      color: #2c3e50;\n      font-weight: 600;\n    }\n\n    .donation-links {\n      display: flex;\n      flex-direction: column;\n      gap: 12px;\n      margin-top: 20px;\n      text-align: center;\n    }\n\n    .donation-links a {\n      color: #007bff;\n      text-decoration: none;\n      transition: color 0.2s;\n    }\n\n    .donation-links a:hover {\n      color: #0056b3;\n    }\n\n    /* 统一关闭按钮样式 */\n    .close-button {\n      position: absolute;\n      top: -20px;\n      right: -20px;\n      width: 36px;\n      height: 36px;\n      border: none;\n      background: #dc3545;\n      border-radius: 50%;\n      font-size: 20px;\n      color: white;\n      cursor: pointer;\n      transition: all 0.3s ease;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      box-shadow: 0 2px 8px rgba(220, 53, 69, 0.4);\n      z-index: 1;\n    }\n\n    .close-button:hover {\n      background: #c82333;\n      transform: scale(1.1) rotate(90deg);\n      box-shadow: 0 4px 12px rgba(220, 53, 69, 0.6);\n    }\n  ');var L=window.location.href,A="downloadCount",O="donationPopupShown",I="firstExecutionv42",B=parseInt(localStorage.getItem(A))||0,D="true"===localStorage.getItem(O),G="true"===localStorage.getItem(I),N=void 0;if(G||(function(){k();var n=document.createElement("div");n.classList.add("overlay"),document.body.appendChild(n);var e=document.createElement("div");e.classList.add("update-log-popup"),e.innerHTML='\n              <div class="update-log-header">\n                  <p><a target="_blank" href="http://greasyfork.icu/zh-CN/scripts/467062">孔夫子旧书网图片下载(自动去水印)更新日志</a></p>\n                  <div style="font-size: 12px; color: #666; text-align: center;">每次升级后此窗口可能会展示多次</div>\n              </div>\n              <div class="update-log-body">\n                  <ul>\n                    <li>\n                      <div style="display: flex; align-items: center; justify-content: center;">🧨提前祝大家新年快乐🧨</div>\n                      <p style="font-weight: bold;">[2025-01-22] v4.2</p>\n                      <ul>\n                          <li style="color: red;">自动根据要下载的图片尺寸计算水印区域,不再需要手动设置</li>\n                      </ul>\n                    </li>\n                    <li>\n                      <p style="font-weight: bold;">[2024-12-27] v4.0</p>\n                      <ul>\n                          <li style="color: red;">1. 新增三种备用去水印方式,分别是:裁剪底部水印区域、裁剪底部水印区域、裁剪底部水印区域;<br><img src="https://greasyfork.s3.us-east-2.amazonaws.com/vb9gy3e8gy70l2r26vw3lgo5bfix" alt="设置菜单说明" style="width: 90%;"></li>\n                          <li>2. 修改按钮和弹窗样式。</li>\n                      </ul>\n                    </li>\n                  </ul>\n                  <p style="text-align: center; margin-top: 10px;">\n                      <a href="#" id="donation" style="color: #007bff; text-decoration: none;">\n                          💰 好活,当赏\n                      </a>\n                      &nbsp;|&nbsp;\n                      <a href="#" id="scyspromotion" style="color: #007bff; text-decoration: none;">\n                          💵 副业社群体检卡\n                      </a>\n                      &nbsp;|&nbsp;\n                      <a href="#" id="devService" style="color: #007bff; text-decoration: none;">\n                          💻 软件/脚本/自动化定制开发\n                      </a>\n                  </p>\n              </div>\n              <div class="update-log-footer">\n                  <button id="closeUpdateLogBtn" class="update-log-button">我知道了</button>\n              </div>\n          ',document.body.appendChild(e),e.querySelector("#closeUpdateLogBtn").addEventListener("click",function(){e.remove(),n.remove()});var t=e.querySelector("#donation"),o=e.querySelector("#scyspromotion"),r=e.querySelector("#devService");t.addEventListener("click",function(n){n.preventDefault(),g()}),o.addEventListener("click",function(n){n.preventDefault(),f("https://greasyfork.s3.us-east-2.amazonaws.com/7cjf1r8rohkrh8xwp0mn2srocx0u")}),r.addEventListener("click",function(n){n.preventDefault(),z()})}(),function(){G=!0,localStorage.setItem(I,"true")}()),L.includes("//search.kongfz.com/"))console.log("//search.kongfz.com/"),N=setInterval(b,1e3);else if(L.includes("//book.kongfz.com/C"))console.log("//book.kongfz.com/C"),N=setInterval(y,1e3);else if(L.includes("//book.kongfz.com/")){console.log("//book.kongfz.com/");var P=function(n){var e=document.createElement("button");return e.innerText="👉 下载图片("+n.length+")",e.id="downloadButton",e.style.backgroundColor="#8c222c",e.style.color="white",document.body.appendChild(e),e}(p(document));P.addEventListener("click",function(){return l(document,P)})}else L.includes("//item.kongfz.com/")&&(console.log("//item.kongfz.com/"),N=setInterval(w,1e3));GM_addStyle("\n    #downloadButton {\n    position: fixed;\n    bottom: 20px;\n    right: 20px;\n    padding: 10px 20px;\n    background-color: #333;\n    color: #fff;\n    border: none;\n    border-radius: 5px;\n    cursor: pointer;\n    z-index: 9999;\n    }\n    #bugReportLink {\n    position: fixed;\n    bottom: 5px;\n    right: 20px;\n    padding: 10px 20px;\n    background-color: #333;\n    color: #fff;\n    border: none;\n    border-radius: 5px;\n    cursor: pointer;\n    z-index: 9999;\n    }\n    .searchPageDownloadButton {\n    padding: 1px 5px;\n    background-color: #333;\n    color: #fff;\n    border: none;\n    border-radius: 3px;\n    cursor: pointer;\n    z-index: 9999;\n    font-size: 12px;\n    margin: 0px 10px;\n    }\n    .bookListPageDownloadButton {\n    padding: 1px 5px;\n    background-color: #333;\n    color: #fff;\n    border: none;\n    border-radius: 3px;\n    cursor: pointer;\n    z-index: 9999;\n    font-size: 12px;\n    margin: 8px auto 0;\n    display: block;\n    }\n    button.disabled {\n    background-color: #ccc;\n    color: #999;\n    cursor: pointer;\n    /* 其他样式 */\n    }\n  .overlay {\n      position: fixed;\n      top: 0;\n      left: 0;\n      width: 100%;\n      height: 100%;\n      background: rgba(0, 0, 0, 0.5);\n      backdrop-filter: blur(5px);\n      z-index: 1000;\n  }\n  .donation-popup {\n      position: fixed;\n      top: 50%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      background: white;\n      padding: 20px;\n      border-radius: 10px;\n      box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);\n      text-align: center;\n      z-index: 10001;\n      max-width: 800px;\n      width: 90%;\n  }\n  .donation-header p {\n      margin: 5px 0;\n      font-size: 18px;\n      font-weight: bold;\n      color: #333;\n  }\n  .donation-body p {\n      font-size: 14px;\n      color: #555;\n      line-height: 1.5;\n  }\n  .donation-images {\n      display: flex;\n      justify-content: space-around;\n      margin: 15px 0;\n  }\n  .donation-image-large {\n      max-width: 350px;\n      max-height: 350px;\n      border: 1px solid #ddd;\n      border-radius: 5px;\n  }\n  .donation-footer {\n      margin-top: 20px;\n  }\n  .donation-button {\n      margin: 5px;\n      padding: 10px 20px;\n      font-size: 14px;\n      border: none;\n      border-radius: 5px;\n      cursor: pointer;\n  }\n  .donation-button.donate {\n      background-color: #28a745;\n      color: white;\n  }\n  .donation-button.cancel {\n      background-color: #dc3545;\n      color: white;\n  }\n  .donation-button:hover {\n      opacity: 0.9;\n  }\n  .image-popup {\n      position: fixed;\n      top: 50%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      background: white;\n      border-radius: 10px;\n      box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);\n      padding: 10px;\n      z-index: 10002;\n  }\n  .image-popup img {\n      max-width: 700px;\n      max-height: 90vh;\n      border-radius: 5px;\n      padding: 20px 50px;\n  }\n  .image-popup .close-button {\n      position: absolute;\n      top: 0px;\n      right: 0px;\n      background: #dc3545;\n      color: white;\n      border: none;\n      border-radius: 50%;\n      width: 30px;\n      height: 30px;\n      font-size: 16px;\n      text-align: center;\n      cursor: pointer;\n  }\n  .update-log-popup {\n      position: fixed;\n      top: 50%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      background: white;\n      padding: 20px;\n      border-radius: 10px;\n      box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);\n      text-align: left;\n      z-index: 10001;\n      max-height: 80vh;\n      overflow-y: auto;\n      max-width: 800px;\n      width: 90%;\n      scrollbar-width: none;\n  }\n      \n  .update-log-header p {\n      margin: 5px 0;\n      font-size: 18px;\n      font-weight: bold;\n      color: #333;\n      text-align: center;\n  }\n  .update-log-body ul {\n      list-style-type: disc;\n      padding-left: 20px;\n  }\n  .update-log-body ul ul {\n      list-style-type: circle;\n      padding-left: 20px;\n  }\n  .update-log-body li {\n      margin-bottom: 2px;\n  }\n  .update-log-footer {\n      margin-top: 20px;\n      text-align: center;\n  }\n  .update-log-button {\n      padding: 5px 10px;\n      font-size: 14px;\n      border: none;\n      border-radius: 5px;\n      cursor: pointer;\n      background-color: #007bff;\n      color: white;\n  }\n  .update-log-button:hover {\n      opacity: 0.9;\n  }\n  \n    "),GM_addStyle("\n    .fireworks-container {\n      position: fixed;\n      top: 0;\n      left: 0;\n      width: 100%;\n      height: 100%;\n      pointer-events: none;\n      z-index: 9999;\n    }\n\n    .firework {\n      position: absolute;\n      transform: scale(1);\n      animation: scale 0.3s ease-out forwards;\n    }\n\n    .particle {\n      position: absolute;\n      width: 6px;  // 增大粒子尺寸\n      height: 6px;\n      border-radius: 50%;\n      animation: explode 1.5s ease-out forwards;\n      box-shadow: 0 0 10px 2px currentColor;  // 添加发光效果\n    }\n\n    @keyframes scale {\n      from {\n        transform: scale(0);\n      }\n      50% {\n        transform: scale(1.2);\n      }\n      to {\n        transform: scale(1);\n      }\n    }\n\n    @keyframes explode {\n      0% {\n        transform: translateX(0) translateY(0);\n        opacity: 1;\n      }\n      50% {\n        opacity: 0.8;\n      }\n      100% {\n        transform: translateX(var(--x)) translateY(var(--y));\n        opacity: 0;\n      }\n    }\n  "),document.addEventListener("DOMContentLoaded",function(){for(var n=document.createElement("style"),e="",t=0;t<20;t++){var o=18*t+(20*Math.random()-10),r=100+50*Math.random();e+=".firework .particle:nth-child("+(t+1)+") { --x: "+Math.cos(o*Math.PI/180)*r+"px; --y: "+Math.sin(o*Math.PI/180)*r+"px; }\n"}n.textContent=e,document.head.appendChild(n)}),GM_addStyle("\n    .confetti-container {\n      position: fixed;\n      top: 0;\n      left: 0;\n      width: 100%;\n      height: 100%;\n      pointer-events: none;\n      z-index: 9999;\n      overflow: hidden;\n    }\n\n    .confetti {\n      position: absolute;\n      width: 10px;\n      height: 20px;\n      top: -20px;\n      transform-origin: center;\n      animation: confetti-fall 3s ease-in-out forwards;\n    }\n\n    @keyframes confetti-fall {\n      0% {\n        transform: translateY(0) rotate(0) scale(1);\n        opacity: 1;\n      }\n      \n      25% {\n        transform: translateY(25vh) rotate(90deg) scale(0.9);\n        opacity: 0.8;\n      }\n      \n      50% {\n        transform: translateY(50vh) rotate(180deg) scale(0.8);\n        opacity: 0.6;\n      }\n      \n      75% {\n        transform: translateY(75vh) rotate(270deg) scale(0.7);\n        opacity: 0.4;\n      }\n      \n      100% {\n        transform: translateY(100vh) rotate(360deg) scale(0.6);\n        opacity: 0;\n      }\n    }\n  "),GM_addStyle('\n    .dev-service-popup {\n      position: fixed;\n      top: 50%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      background: white;\n      padding: 30px;\n      border-radius: 16px;\n      box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);\n      z-index: 10004;\n      max-width: 800px;\n      width: 90%;\n    }\n\n    .dev-service-header {\n      position: relative;\n      text-align: center;\n      margin-bottom: 25px;\n      padding-bottom: 15px;\n      border-bottom: 2px solid #f0f2f5;\n    }\n\n    .dev-service-header h3 {\n      margin: 0;\n      font-size: 24px;\n      color: #2c3e50;\n      font-weight: 600;\n    }\n\n    .close-button {\n      position: absolute;\n      top: -10px;\n      right: -10px;\n      width: 30px;\n      height: 30px;\n      border: none;\n      background: #dc3545;\n      border-radius: 50%;\n      font-size: 20px;\n      color: white;\n      cursor: pointer;\n      transition: all 0.3s ease;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n    }\n\n    .close-button:hover {\n      background: #c82333;\n      transform: scale(1.1) rotate(90deg);\n      box-shadow: 0 4px 12px rgba(220, 53, 69, 0.6);\n    }\n\n    .service-sections {\n      display: flex;\n      gap: 40px;\n      margin-bottom: 30px;\n      padding: 20px;\n      background: #f8fafc;\n      border-radius: 12px;\n    }\n\n    .service-intro {\n      flex: 1;\n      padding: 20px;\n      background: white;\n      border-radius: 10px;\n      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);\n    }\n\n    .service-intro h4 {\n      color: #2c3e50;\n      margin: 0 0 15px;\n      font-size: 18px;\n      font-weight: 600;\n      display: flex;\n      align-items: center;\n      gap: 8px;\n    }\n\n    .service-intro ul {\n      list-style: none;\n      padding: 0;\n      margin: 0;\n    }\n\n    .service-intro li {\n      padding: 8px 0 8px 24px;\n      position: relative;\n      color: #34495e;\n      font-size: 15px;\n      line-height: 1.5;\n    }\n\n    .service-intro li:before {\n      content: "✓";\n      position: absolute;\n      left: 0;\n      color: #3498db;\n      font-weight: bold;\n    }\n\n    .contact-info {\n      text-align: center;\n      padding-top: 20px;\n      border-top: 2px solid #f0f2f5;\n    }\n\n    .contact-qr {\n      margin-bottom: 15px;\n    }\n\n    .contact-qr img {\n      max-width: 180px;\n      border-radius: 10px;\n      margin-bottom: 12px;\n      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n      transition: transform 0.3s ease;\n    }\n\n    .contact-qr img:hover {\n      transform: scale(1.05);\n    }\n\n    .contact-qr p {\n      margin: 5px 0;\n      color: #2c3e50;\n      font-weight: 600;\n      font-size: 16px;\n    }\n\n    .contact-note {\n      color: #7f8c8d;\n      font-size: 14px;\n      margin: 0;\n    }\n\n    @media (max-width: 768px) {\n      .service-sections {\n        flex-direction: column;\n        gap: 20px;\n      }\n      \n      .dev-service-popup {\n        padding: 20px;\n      }\n      \n      .service-intro {\n        padding: 15px;\n      }\n    }\n  ')}();