文章导出成pdf

将一些主流的网站的文章,去除掉一些无关部分直接启动浏览器自带打印功能

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @name         文章导出成pdf
// @namespace    https://github.com/Vanisper/web-article-to-pdf
// @version      1.3.2
// @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/*
// @match        https://www.zhihu.com/question/*/answer/*
// @match        https://www.zhihu.com/question/*
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.global.prod.js
// @description 将一些主流的网站的文章,去除掉一些无关部分直接启动浏览器自带打印功能
// ==/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}.setpdf[data-v-af70e9ff]{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, #toolbarBox #csdn-toolbar, body > div:nth-child(49) > div, #toolBarBox, #mainBox > main > div.recommend-box, #recommendNps, #copyright-box, #treeSkill > div, .csdn-side-toolbar, .left-toolbox",
      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;
            }
            #toolBarBox, #csdn-toolbar, .recommend-right, .recommend-right1, .blog_container_aside {
                display: none !important;
            }
        }`,
      copyrightTarget: ".blog-content-box"
    }
  ];
  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;
            }
        }`
    },
    // 知乎提问板块-指定某个回答
    {
      url: "https?://www.zhihu.com/question/\\d+/answer/\\d+",
      name: "zhihu",
      class: ".AppHeader, .Question-sideColumn, .ContentItem-actions, .CornerButtons, .MoreAnswers, .ViewAll",
      style: `
        @media print {
            .ListShortcut{
                width: 100%;
            }
            .Question-mainColumn {
                width: 100%;
            }
        }`
    },
    {
      url: "https?://www.zhihu.com/question/\\d+",
      name: "zhihu",
      class: ".AppHeader, .Question-sideColumn, .ContentItem-actions, .CornerButtons, .MoreAnswers, .ViewAll",
      style: `
        @media print {
            .ListShortcut{
                width: 100%;
            }
            .Question-mainColumn {
                width: 100%;
            }
        }`,
      hideDefault: true,
      javascript: () => {
        var _a;
        const listItem = (_a = document.querySelector(".AnswersNavWrapper")) == null ? void 0 : _a.querySelectorAll(".List-item");
        if (!listItem)
          return false;
        const printItem = (doc, url) => {
          if (!doc)
            return false;
          window.open(
            url,
            "_blank",
            "width=1080,height=800,menubar=yes,scrollbars=yes,resizable=yes"
          );
        };
        listItem.forEach((item, index) => {
          var _a2, _b;
          const box = item.querySelector(".AnswerItem-authorInfo");
          const name = (_b = (_a2 = item.querySelector(".AnswerItem")) == null ? void 0 : _a2.attributes.getNamedItem("name")) == null ? void 0 : _b.value;
          if (!box || !name)
            return false;
          const printBtn = document.createElement("button");
          printBtn.innerHTML = "打印当前回答";
          printBtn.className = "print-btn_" + index;
          const url = window.location.href + `/answer/${name}`;
          printBtn.onclick = () => {
            printItem(item, url);
          };
          box.append(printBtn);
        });
      }
    }
  ];
  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: "",
        /** 版权信息将插入的css选择器 */
        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;
            curr.target = e.copyrightTarget || "body";
            curr.js = e.javascript;
            curr.hideDefault = e.hideDefault;
            return true;
          }
        });
        if (flag.value) {
          var style2 = document.createElement("style");
          style2.innerHTML = `@media print {${curr.class}, .mod, button.setpdf, .web-article-to-pdf { 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);
            curr.js && (() => {
              curr.js();
            })();
          }, 200);
          curr.hideDefault && (flag.value = false);
        }
      });
      vue.onUnmounted(() => {
        draggableInstance.destroy();
      });
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
          vue.withDirectives(vue.createVNode(button1, {
            onClick: action,
            class: "setpdf",
            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-af70e9ff"]]);
  vue.createApp(App).mount(
    (() => {
      const app = document.createElement("div");
      app.classList.add("web-article-to-pdf");
      document.body.append(app);
      return app;
    })()
  );

})(Vue);