// ==UserScript== // @name 文章导出成pdf // @namespace https://github.com/Vanisper/web-article-to-pdf // @version 1.3.1 // @author Vanisper // @license MIT // @icon https://vitejs.dev/logo.svg // @defaulticon 将一些主流的网站的文章,去除掉一些无关部分直接启动浏览器自带打印功能 // @match https://www.bilibili.com/read/cv* // @match https://www.cnblogs.com/*/p/* // @match https://www.cnblogs.com/*/archive/* // @match https://blog.csdn.net/*/article/details/* // @match https://www.jianshu.com/p/* // @match https://juejin.cn/post/* // @match https://segmentfault.com/a/* // @match https://mp.weixin.qq.com/s/* // @match https://mp.weixin.qq.com/s?* // @match https://zhuanlan.zhihu.com/p/* // @require https://cdn.jsdelivr.net/npm/vue@3.2.47/dist/vue.global.prod.js // @description 将一些主流的网站的文章,去除掉一些无关部分直接启动浏览器自带打印功能 // @downloadURL none // ==/UserScript== (e=>{const t=document.createElement("style");t.dataset.source="vite-plugin-monkey",t.textContent=e,document.head.append(t)})(" *{padding:0;margin:0}button[data-v-13bc6f6b]{font-weight:700;color:#fff;border-radius:2rem;width:95.02px;height:42.66px;border:none;background-color:#3653f8;display:flex;justify-content:center;align-items:center}button .span-mother[data-v-13bc6f6b]{display:flex;overflow:hidden}button .span-mother span[data-v-13bc6f6b]{display:flex;justify-content:center;align-items:center}button .span-mother2[data-v-13bc6f6b]{display:flex;position:absolute;overflow:hidden}button .span-mother2 span[data-v-13bc6f6b]{transform:translateY(-1.2em);display:flex;justify-content:center;align-items:center}button:hover .span-mother[data-v-13bc6f6b]{position:absolute}button:hover .span-mother span[data-v-13bc6f6b]{transform:translateY(1.2em)}button:hover .span-mother2 span[data-v-13bc6f6b]{transform:translateY(0)}@keyframes spin-19ff1008{to{transform:rotate(360deg)}}#loading[data-v-19ff1008]{position:fixed;display:flex;top:0;left:0;width:100%;height:100%;background-color:#8ae79d82;z-index:9999}#loading .spinner[data-v-19ff1008]{margin:auto;width:40px;height:40px;border-radius:50%;border:3px solid transparent;border-top-color:#fff;animation:spin-19ff1008 .8s ease infinite}.draggable[data-v-964d3ff2]{position:fixed;top:100px;right:24px;box-sizing:border-box;cursor:pointer;user-select:none;transition:opacity .2s ease .1s;z-index:9998} "); (function (vue) { 'use strict'; var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => { __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); return value; }; class useDraggable { // dom初始top constructor(element) { __publicField(this, "draggableElement"); __publicField(this, "isDragging"); __publicField(this, "isDraggable"); __publicField(this, "startPosition"); __publicField(this, "currentX"); // dom初始left __publicField(this, "currentY"); __publicField(this, "startDragging", (event) => { const elementRect = this.draggableElement.getBoundingClientRect(); this.startPosition = { x: elementRect.x, y: elementRect.y }; this.currentX = elementRect.left; this.currentY = elementRect.top; this.isDragging = true; this.startPosition = { x: event.clientX, y: event.clientY }; window.addEventListener("mousemove", this.dragging); window.addEventListener("mouseup", this.stopDragging); }); __publicField(this, "dragging", (event) => { if (this.isDragging && this.draggableElement) { const maxLeft = document.documentElement.clientWidth - this.draggableElement.offsetWidth; const maxTop = document.documentElement.clientHeight - this.draggableElement.offsetHeight; const offsetX = event.clientX - this.startPosition.x; const offsetY = event.clientY - this.startPosition.y; let left = this.currentX + offsetX; let top = this.currentY + offsetY; if (offsetX < 0) { left = Math.max(0, left); } else { left = Math.min(maxLeft, left); } if (offsetY < 0) { top = Math.max(0, top); } else { top = Math.min(maxTop, top); } this.draggableElement.style.position = "fixed"; this.draggableElement.style.top = top + "px"; this.draggableElement.style.left = left + "px"; } }); __publicField(this, "stopDragging", (event) => { this.isDragging = false; window.removeEventListener("mousemove", this.dragging, false); window.removeEventListener("mouseup", this.stopDragging, false); }); __publicField(this, "resetPosition", () => { const elementRect = this.draggableElement.getBoundingClientRect(); this.draggableElement.style.position = "fixed"; if (window.innerWidth < elementRect.right) { this.draggableElement.style.left = window.innerWidth - elementRect.width + "px"; } if (window.innerHeight < elementRect.bottom) { this.draggableElement.style.top = window.innerHeight - elementRect.height + "px"; } if (elementRect.top < 0) { this.draggableElement.style.top = "0px"; } }); this.draggableElement = element; this.isDraggable = element.getAttribute("draggable") === "true" || element.getAttribute("draggable") === "" ? true : false; this.isDragging = false; const elementRect = element.getBoundingClientRect(); this.startPosition = { x: elementRect.x, y: elementRect.y }; this.currentX = elementRect.left; this.currentY = elementRect.top; this.init(); } init() { var _a; this.unDraggable(); const elementRect = this.draggableElement.getBoundingClientRect(); this.draggableElement.style.position = "fixed"; this.draggableElement.style.left = elementRect.left + "px"; this.draggableElement.style.top = elementRect.top + "px"; this.draggableElement.style.right = "unset"; window.addEventListener("resize", this.resetPosition); (_a = this.draggableElement) == null ? void 0 : _a.addEventListener("mousedown", this.startDragging); } draggable() { var _a; (_a = this.draggableElement) == null ? void 0 : _a.setAttribute("draggable", "true"); this.isDraggable = true; } unDraggable() { var _a; (_a = this.draggableElement) == null ? void 0 : _a.setAttribute("draggable", "false"); this.isDraggable = false; } preventDefault(event) { event.preventDefault(); } destroy() { var _a; (_a = this.draggableElement) == null ? void 0 : _a.removeEventListener("mousedown", this.startDragging); window.removeEventListener("resize", this.resetPosition); } } const _hoisted_1$1 = { class: "span-mother" }; const _hoisted_2$1 = { class: "span-mother2" }; const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({ __name: "button1", props: { text: { type: String, default: "" } }, setup(__props) { const props = __props; vue.ref(props.text.length); return (_ctx, _cache) => { return vue.openBlock(), vue.createElementBlock("button", null, [ vue.createElementVNode("span", _hoisted_1$1, [ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.text, (item, index) => { return vue.openBlock(), vue.createElementBlock("span", { key: item, style: vue.normalizeStyle({ transition: `${0.1 * index + 0.1}s` }) }, vue.toDisplayString(item), 5); }), 128)) ]), vue.createElementVNode("span", _hoisted_2$1, [ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.text, (item, index) => { return vue.openBlock(), vue.createElementBlock("span", { key: item, style: vue.normalizeStyle({ transition: `${0.1 * index + 0.1}s` }) }, vue.toDisplayString(item), 5); }), 128)) ]) ]); }; } }); const _export_sfc = (sfc, props) => { const target = sfc.__vccOpts || sfc; for (const [key, val] of props) { target[key] = val; } return target; }; const button1 = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-13bc6f6b"]]); const _sfc_main$1 = {}; const _withScopeId = (n) => (vue.pushScopeId("data-v-19ff1008"), n = n(), vue.popScopeId(), n); const _hoisted_1 = { id: "loading" }; const _hoisted_2 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "spinner" }, null, -1)); const _hoisted_3 = [ _hoisted_2 ]; function _sfc_render(_ctx, _cache) { return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, _hoisted_3); } const loading1 = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render], ["__scopeId", "data-v-19ff1008"]]); const bilibiliRules = [{ url: "https?://www.bilibili.com/read/cv\\w+", name: "bilibili", class: "#bili-header-container, div.article-breadcrumb, div.right-side-bar.on.is-mini-page, #comment-wrapper, div.fixed-top-header,#readRecommendInfo, div.interaction-info", style: `@media print { #app > div > div.article-container {} }` }]; const cnblogsRules = [ { url: "https?://www\\.cnblogs\\.com/\\w+/(p|archive)/\\w+", name: "cnblogs", class: "#top_nav, #header, #sideBar,#blog_post_info,#post_next_prev,#topics > div > div.postDesc,#comment_form,#footer,#top_nav,#header,#mylinks,#mytopmenu,body > div.footer,#leftcontent,#blog_post_info_block,#comment_form", style: `@media print { #main { display: flex !important; } #mainContent { max-width: 1080px!important; min-width: 720px!important; width: 100%!important; } #post_detail { display: flex !important; justify-content: center; } }` } ]; const csdnRules = [ { url: "https?://blog\\.csdn\\.net/\\w+/article/details/\\w+", name: "csdn", class: "#mainBox > aside, #csdn-toolbar, body > div:nth-child(49) > div, #toolBarBox,#mainBox > main > div.recommend-box, #recommendNps,#copyright-box, #treeSkill > div", style: `@media print { #mainBox > main > div.blog-content-box{ position: absolute; top: 0; left: 0; max-width: 1080px; z-index: 999; } main div.blog-content-box pre.set-code-hide { height: auto; overflow-y: auto; } main div.blog-content-box pre.set-code-hide .hide-preCode-box { display: none; } #article_content .markdown_views pre.prettyprint * { white-space: pre-wrap; word-break: break-word; word-wrap: normal; } }` } ]; const jianshuRules = [{ url: "https?://www.jianshu.com/p/\\w+", name: "jianshu", class: "#__next > header, #__next aside,#__next > div._3Pnjry, #__next > footer, #__next > div > div > div._gp-ck > section:nth-child(1) > div._13lIbp, #__next > div > div > div._gp-ck > section:nth-child(2), #__next > div._21bLU4._3kbg6I > div > div._gp-ck > section:nth-child(5),#note-page-comment", style: `@media print { #__next > div._21bLU4._3kbg6I > div > div._gp-ck > section:nth-child(1) { position: absolute; top: 0; left: 0;z-index: 999; max-width: 1080px; min-width: 1080px; width: 1080px; } }` }]; const juejinRules = [ { url: "https?://juejin.cn/post/\\w+", name: "juejin", class: "#juejin > div.view-container > div, #juejin > div.view-container > main > div > div.article-suspended-panel.dynamic-data-ready,#juejin > div.view-container > main > div > div.main-area.article-area > div.wrap.category-course-recommend,#comment-box,#juejin > div.view-container > main > div > div.main-area.recommended-area.shadow,#juejin > div.view-container > main > div > div.recommended-links.main-area,#juejin > div.view-container > main > div > div.sidebar.sidebar,#juejin > div.global-component-box, #juejin > div.view-container > main > div > div.main-area.article-area > div.article-end > div.column-container,#juejin > div.view-container > main > div > div.main-area.article-area > div.article-end > div.extension-banner,#juejin > div.recommend-box,#juejin > div.view-container > main > div > div.main-area.article-area > div.action-box.action-bar", style: `@media print { article { position: absolute; top: 0; left: 0;z-index: 999; max-width: 1080px; min-width: 1080px; width: 1080px; } }` } ]; const segmentfaultRules = [ { url: "https?://segmentfault.com/a/\\w+", name: "segmentfault", class: ".fix-bottom-action-wrap, nav, .right-side, .sticky-wrap, #comment-area, div.article-content div.card.mt-4", style: `@media print { .fmt pre {max-height: unset !important; } }`, copyright: "" } ]; const weixinRules = [ { url: "https?://mp.weixin.qq.com/s(\\?|/)\\w+", name: "weixin", class: "#js_base_container > div.rich_media_area_extra, #js_pc_qr_code", style: `@media print {}` } ]; const zhihuRules = [ { url: "https?://zhuanlan.zhihu.com/p/\\w+", name: "zhihu", class: ".Catalog, .ColumnPageHeader-Wrapper, .RichContent-actions, .RichContent-actions, .Post-NormalSub, .Post-SideActions, .complementary, .CornerAnimayedFlex", style: `@media print { article > div, article > header { max-width: 1080px; min-width: 1080px; width: 1080px; } }` } ]; const rules = [ ...bilibiliRules, ...cnblogsRules, ...csdnRules, ...jianshuRules, ...juejinRules, ...segmentfaultRules, ...weixinRules, ...zhihuRules ]; const _sfc_main = /* @__PURE__ */ vue.defineComponent({ __name: "App", setup(__props) { const dragDomRef = vue.ref(); let draggableInstance; const isShow = vue.ref(false); function preventDefault(e) { e.preventDefault(); } const action = () => { stopScroll.value = false; isShow.value = true; window.addEventListener("wheel", preventDefault, { passive: false }); window.scrollTo(0, 0); smoothScrollToBottom(); }; const stopScroll = vue.ref(false); const stop = () => { stopScroll.value = true; }; function smoothScrollToBottom() { var scrollHeight = document.body.scrollHeight; var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; var clientHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; if (stopScroll.value) { isShow.value = false; window.removeEventListener("wheel", preventDefault); return; } if (scrollTop + clientHeight >= scrollHeight) { isShow.value = false; window.removeEventListener("wheel", preventDefault); setTimeout(() => { window.print(); }, 200); return; } else { window.scrollTo({ top: scrollTop + clientHeight, behavior: "auto" // 可以设置成光滑的 }); setTimeout(smoothScrollToBottom, 1e3); } } const currentUrl = window.location.href; let curr = { url: "", name: "", class: "", style: "", target: "body" }; const flag = vue.ref(false); vue.onMounted(() => { flag.value = rules.some((e) => { var reg = new RegExp(e.url); if (reg.test(currentUrl)) { curr.url = currentUrl; curr.name = e.name; curr.class = e.class; curr.style = e.style; return true; } }); if (flag.value) { var style2 = document.createElement("style"); style2.innerHTML = `@media print {${curr.class}, .mod, a.setpdf { display: none!important;} div.setpdf-copyright { display: block!important; }} ${curr.style}`; document.head.appendChild(style2); const target = document.querySelector(curr.target); const copyright = document.createElement("div"); copyright.setAttribute("style", "display:none"); copyright.setAttribute("class", "setpdf-copyright"); copyright.appendChild(document.createTextNode("来源:")); const link = document.createElement("a"); link.textContent = currentUrl; link.setAttribute("href", currentUrl); copyright.appendChild(link); target.appendChild(copyright); setTimeout(() => { draggableInstance = new useDraggable(dragDomRef.value.$el); }, 200); } }); vue.onUnmounted(() => { draggableInstance.destroy(); }); return (_ctx, _cache) => { return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [ vue.withDirectives(vue.createVNode(button1, { onClick: action, class: "draggable", text: "导出PDF", draggable: "true", ref_key: "dragDomRef", ref: dragDomRef }, null, 512), [ [vue.vShow, flag.value] ]), vue.withDirectives(vue.createVNode(loading1, { onDblclick: stop }, null, 512), [ [vue.vShow, flag.value && isShow.value] ]) ], 64); }; } }); const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-964d3ff2"]]); vue.createApp(App).mount( (() => { const app = document.createElement("div"); app.classList.add("web-article-to-pdf"); document.body.append(app); return app; })() ); })(Vue);