您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
2024/2/25 21:45:23
当前为
// ==UserScript== // @name ExportPDF // @namespace Violentmonkey Scripts // @match *://www.doc88.com/* // @match http://localhost:8080/ // @match https://cn.bing.com/* // @grant none // @version 1.1 // @author louiesun // @license GPL-3.0-or-later // @description 2024/2/25 21:45:23 // ==/UserScript== //不能跑!! 测试请引用下方js can't run, please require the js above // https://github.com/devongovett/pdfkit/releases/download/v0.14.0/pdfkit.standalone.js // https://github.com/devongovett/blob-stream/releases/download/v0.1.3/blob-stream.js // https://github.com/eligrey/FileSaver.js/blob/master/dist/FileSaver.min.js /* * * A canvas to PDF converter. Uses a mock canvas context to build a PDF document. * * Licensed under the MIT license: * http://www.opensource.org/licenses/mit-license.php * * Author: * Joshua Gould * * Copyright (c) 2017 Joshua Gould */ function hex(v) { return v < 0x10 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16); } function hslToHex(h, s, l, a) { h = (h % 360) + (h < 0) * 360; s = isNaN(h) || isNaN(s) ? 0 : s; const m2 = l + (l < 0.5 ? l : 1 - l) * s; const m1 = 2 * l - m2; return rgbToHex( hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), hsl2rgb(h, m1, m2), hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), a, ); } function hsl2rgb(h, m1, m2) { return ( (h < 60 ? m1 + ((m2 - m1) * h) / 60 : h < 180 ? m2 : h < 240 ? m1 + ((m2 - m1) * (240 - h)) / 60 : m1) * 255 ); } const reI = "\\s*([+-]?\\d+)\\s*", reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*", reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*", reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"), reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"), reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"), reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"), reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"), reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$"); const rgbToHex = function (r, g, b, a) { return { c: "#" + hex(r) + hex(g) + hex(b), a: a }; }; const fixColor = function (value) { let m; const format = (value + "").trim().toLowerCase(); if ((m = reRgbInteger.exec(format))) { // rgb(255, 0, 0) return rgbToHex(m[1], m[2], m[3], 1); } else if ((m = reRgbPercent.exec(format))) { // // rgb(100%, 0%, 0%) return rgbToHex( (m[1] * 255) / 100, (m[2] * 255) / 100, (m[3] * 255) / 100, 1, ); } else if ((m = reRgbaInteger.exec(format))) { // // rgba(255, 0, 0, 0.5) return rgbToHex(m[1], m[2], m[3], m[4]); } else if ((m = reRgbaPercent.exec(format))) { // // rgb(100%, 0%, 0%, .2) return rgbToHex( (m[1] * 255) / 100, (m[2] * 255) / 100, (m[3] * 255) / 100, m[4], ); } else if ((m = reHslPercent.exec(format))) { // // hsl(120, 50%, 50%) return hslToHex(m[1], m[2] / 100, m[3] / 100); } else if ((m = reHslaPercent.exec(format))) { return hslToHex(m[1], m[2] / 100, m[3] / 100, m[4]); // hsla(120, 50%, 50%, 1) } else { return { c: value, a: 1 }; } }; /** * * @param stream Stream to write the PDF to. * @param options Options passed to PDFDocument constructor. * @constructor */ const PdfContext = function (stream, options) { if (stream == null) { throw new Error("Stream must be provided."); } const doc = new PDFDocument(options); this.stream = doc.pipe(stream); let fontValue = "10px Helvetica"; let textAlign = "left"; let textBaseline = "alphabetic"; let lineHeight = doc.currentLineHeight(false); let font = fontValue; const fontRegex = /^\s*(?=(?:(?:[-a-z]+\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\'\"\sa-z]+?)\s*$/i; const defaultFontData = { style: "normal", size: 10, family: "Helvetica", weight: "normal", }; const parseFont = function () { const fontPart = fontRegex.exec(font); if (fontPart === null) { return defaultFontData; } const data = { style: fontPart[1] || "normal", size: parseInt(fontPart[4]) || 10, family: fontPart[6] || "Helvetica", weight: fontPart[3] || "normal", }; return data; }; Object.defineProperty(this, "fillStyle", { get: function () { return doc.fillColor(); }, set: function (value) { const color = fixColor(value); doc.fillColor(color.c, color.a); }, }); Object.defineProperty(this, "strokeStyle", { get: function () { return doc.strokeColor(); }, set: function (value) { const color = fixColor(value); doc.strokeColor(color.c, color.a); }, }); Object.defineProperty(this, "lineWidth", { get: function () { return doc.lineWidth(); }, set: function (value) { doc.lineWidth(value); }, }); Object.defineProperty(this, "lineCap", { get: function () { return doc.lineCap(); }, set: function (value) { doc.lineCap(value); }, }); Object.defineProperty(this, "lineJoin", { get: function () { return doc.lineJoin(); }, set: function (value) { doc.lineJoin(value); }, }); Object.defineProperty(this, "globalAlpha", { get: function () { return doc.opacity(); }, set: function (value) { value >= 0.0 && value <= 1.0 && doc.opacity(value); }, }); Object.defineProperty(this, "font", { get: function () { return fontValue; }, set: function (value) { fontValue = value; const parsedFont = parseFont(value); doc.fontSize(parsedFont.size); doc.font(parsedFont.family); lineHeight = doc.currentLineHeight(false); }, }); this.end = function () { doc.end(); }; this.save = function () { doc.save(); }; this.restore = function () { doc.restore(); }; this.scale = function (x, y) { doc.scale(x, y); }; this.rotate = function (angle) { const degrees = (angle * 180) / Math.PI; doc.rotate(degrees); }; this.translate = function (x, y) { doc.translate(x, y); }; this.transform = function (a, b, c, d, e, f) { doc.transform(a, b, c, d, e, f); }; this.beginPath = function () { // no-op }; this.moveTo = function (x, y) { doc.moveTo(x, y); }; this.closePath = function () { doc.closePath(); }; this.lineTo = function (x, y) { doc.lineTo(x, y); }; this.stroke = function () { doc.stroke(); }; this.fill = function () { doc.fill(); }; this.rect = function (x, y, width, height) { doc.rect(x, y, width, height); }; this.fillRect = function (x, y, width, height) { doc.rect(x, y, width, height); doc.fill(); }; this.strokeRect = function (x, y, width, height) { doc.rect(x, y, width, height); doc.stroke(); }; /** * "Clears" a canvas by just drawing a white rectangle in the current group. */ this.clearRect = function (x, y, width, height) { const oldFill = doc.fillColor(); doc.fillColor("white"); doc.rect(x, y, width, height); doc.fill(); doc.fillColor(oldFill); }; this.arc = function (x, y, r, a0, a1, ccw) { const pi = Math.PI, tau = 2 * pi, epsilon = 1e-6, tauEpsilon = tau - epsilon; (x = +x), (y = +y), (r = +r); let dx = r * Math.cos(a0), dy = r * Math.sin(a0), x0 = x + dx, y0 = y + dy, cw = 1 ^ ccw, da = ccw ? a0 - a1 : a1 - a0; // Is the radius negative? Error. if (r < 0) { throw new Error("negative radius: " + r); } let cmd = ""; // Is this path empty? Move to (x0,y0). cmd += "M" + x0 + "," + y0; // // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0). // else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) { // cmd += 'L' + x0 + ',' + y0; // } // Is this arc empty? We’re done. if (!r) { return; } // Does the angle go the wrong way? Flip the direction. if (da < 0) { da = (da % tau) + tau; } // Is this a complete circle? Draw two arcs to complete the circle. if (da > tauEpsilon) { cmd += "A" + r + "," + r + ",0,1," + cw + "," + (x - dx) + "," + (y - dy) + "A" + r + "," + r + ",0,1," + cw + "," + x0 + "," + y0; } // Is this arc non-empty? Draw an arc! else if (da > epsilon) { cmd += "A" + r + "," + r + ",0," + +(da >= pi) + "," + cw + "," + (x + r * Math.cos(a1)) + "," + (y + r * Math.sin(a1)); } doc.path(cmd); }; this.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) { doc.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); }; this.quadraticCurveTo = function (cpx, cpy, x, y) { doc.quadraticCurveTo(cpx, cpy, x, y); }; this.createLinearGradient = function (x1, y1, x2, y2) { const gradient = doc.linearGradient(x1, y1, x2, y2); gradient.addColorStop = function (offset, color) { const fixedColor = fixColor(color); gradient.stop(offset, fixedColor.c, fixedColor.a); }; return gradient; }; this.createRadialGradient = function (x0, y0, r0, x1, y1, r1) { const gradient = doc.radialGradient(x0, y0, r0, x1, y1, r1); gradient.addColorStop = function (offset, color) { const fixedColor = fixColor(color); gradient.stop(offset, fixedColor.c, fixedColor.a); }; return gradient; }; this.adjustTextX = function (text, x) { if (textAlign !== "start" || textAlign !== "left") { const width = doc.widthOfString(text); if (textAlign === "right" || textAlign === "end") { x -= width; } else if (textAlign === "center") { x -= width / 2; } } return x; }; this.adjustTextY = function (text, y) { // baseline is top by default if (textBaseline === "bottom") { y -= lineHeight; } else if (textBaseline === "middle") { y -= lineHeight / 2; } else if (textBaseline === "alphabetic") { y -= lineHeight / 2 + 1; } return y; }; this.fillText = function (text, x, y) { x = this.adjustTextX(text, x); y = this.adjustTextY(text, y); doc.text(text, x, y, { lineBreak: false, stroke: false, fill: true, }); }; this.strokeText = function (text, x, y) { x = this.adjustTextX(text, x); y = this.adjustTextY(text, y); doc.text(text, x, y, { lineBreak: false, stroke: true, fill: false }); }; this.measureText = function (text) { text = "" + text; const width = doc.widthOfString(text); return { width: width, height: lineHeight }; }; this.clip = function () { doc.clip(); }; this.drawImage = function (image) { const args = Array.prototype.slice.call(arguments); image = args[0]; let dx, dy, dw, dh, sx = 0, sy = 0, sw, sh; if (args.length === 3) { dx = args[1]; dy = args[2]; sw = image.width; sh = image.height; dw = sw; dh = sh; } else if (args.length === 5) { dx = args[1]; dy = args[2]; dw = args[3]; dh = args[4]; sw = image.width; sh = image.height; } else if (args.length === 9) { sx = args[1]; sy = args[2]; sw = args[3]; sh = args[4]; dx = args[5]; dy = args[6]; dw = args[7]; dh = args[8]; } else { throw new Error( "Invalid number of arguments passed to drawImage: " + arguments.length, ); } if (image.nodeName === "IMG") { const canvas = document.createElement("tcanvas"); canvas.width = image.width; canvas.height = image.height; canvas.getContext("2d").drawImage(image, 0, 0); const dataURL = canvas.toDataURL("image/png"); doc.image(dataURL, dx, dy, { width: dw, height: dh }); } else { doc.image(image, dx, dy, { width: dw, height: dh }); } }; this.setTransform = function (a, b, c, d, e, f) { const ctm = doc._ctm; const height = doc.page.height; const [a1, b1, c1, d1, e1, f1] = ctm; const determinant = a1 * d1 - b1 * c1; const inverse = [ d1 / determinant, -b1 / determinant, -c1 / determinant, a1 / determinant, (c1 * f1 - d1 * e1) / determinant, (b1 * e1 - a1 * f1) / determinant, ]; doc.transform( inverse[0], inverse[1], inverse[2], inverse[3], inverse[4], inverse[5], ); doc.translate(0, height); doc.scale(1, -1); doc.transform(a, b, c, d, e, f); }; /** * Not yet implemented */ this.createPattern = function (image, repetition) { console.log("createPattern not implemented"); }; this.setLineDash = function (dashArray) { console.log("setLineDash not implemented"); }; this.drawFocusRing = function () { console.log("drawFocusRing not implemented"); }; this.createImageData = function () { console.log("drawFocusRing not implemented"); }; this.getImageData = function () { console.log("getImageData not implemented"); }; this.putImageData = function () { console.log("putImageData not implemented"); }; this.globalCompositeOperation = function () { console.log("globalCompositeOperation not implemented"); }; this.arcTo = function (x1, y1, x2, y2, radius) { console.log("arcTo not implemented"); }; }; var HTMLElememtNameList=['link','meta','style','script','noscript','template','body','section','nav','article','aside','h1','header','footer','address','main','p','hr','pre','blockquote','ol','ul','li','dl','dt','dd','figure','figcaption','div','a','em','strong','small','s','cite','q','dfn','abbr','data','time','code','var','samp','kbd','sub','i','b','u','mark','ruby','rt','rp','bdi','bdo','span','br','wbr','ins','del','img','iframe','embed','object','param','video','audio','source','track','canvas','map','area','svg','math','table','caption','colgroup','col','tbody','thead','tfoot','tr','td','th','form','fieldset','legend','label','input','button','select','datalist','optgroup','option','textarea','keygen','output','progress','meter','details','summary','menuitem','menu']; var HTMLElementList=new Array(HTMLElememtNameList.length); document.ElementList=HTMLElementList; function ElementInit() { for(let i=0; i<HTMLElememtNameList.length; i++) HTMLElementList[i]=document.createElement(HTMLElememtNameList[i]); } ElementInit(); var Mycanvas=HTMLElementList[HTMLElememtNameList.indexOf("canvas")]; Mycanvas.PDFcontext=new PdfContext(blobStream()); Mycanvas.getContext=function() { return this.PDFcontext; }; var _documentcreateElement = document.createElement; document.createElement = function (tagName, className, parent) { console.log(tagName,className,parent); tagName=tagName.toLowerCase(); var elem; if(tagName == "tcanvas") tagName="canvas"; if (tagName == 'canvas') { elem = Mycanvas; } else if(HTMLElememtNameList.indexOf(tagName)>-1){ // if(HTMLElememtNameList.indexOf(tagName)>-1){ elem = HTMLElementList[HTMLElememtNameList.indexOf(tagName)]; } else { alert("PDFexporter Error!"); console.log(tagName); elem=_documentcreateElement(tagName); } if (className) { elem.className = className || ''; } if (parent) { parent.appendChild(elem); } console.log(elem); return elem; } document.createPDFcanvas=function() { return new PdfContext(blobStream()); } // you may need https://github.com/lisonge/Disable-CSP
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址