diff --git a/README.md b/README.md
index d0b8373..595e819 100644
--- a/README.md
+++ b/README.md
@@ -148,6 +148,7 @@ https://github.com/027xiguapi/code-box
2. [plasmo](https://github.com/PlasmoHQ/plasmo)
3. [Chrome 应用商店一站式支持](https://support.google.com/chrome_webstore/contact/one_stop_support)
4. [开箱即用的web打印和下载](https://juejin.cn/post/7412672713376497727)
+5. [导出微信公众号文章为PDF](https://greasyfork.org/en/scripts/510683-%E5%AF%BC%E5%87%BA%E5%BE%AE%E4%BF%A1%E5%85%AC%E4%BC%97%E5%8F%B7%E6%96%87%E7%AB%A0%E4%B8%BApdf/code)
## 隐私政策
diff --git a/component/items/downloadPdf.tsx b/component/items/downloadPdf.tsx
new file mode 100644
index 0000000..5b184ea
--- /dev/null
+++ b/component/items/downloadPdf.tsx
@@ -0,0 +1,25 @@
+import { DownloadOutlined, StarTwoTone } from "@ant-design/icons"
+
+import { sendToContentScript } from "@plasmohq/messaging"
+
+import { i18n } from "~tools"
+
+export default function DownloadPdf(props) {
+ let { name } = props
+
+ async function downloadPdf() {
+ sendToContentScript({
+ name: `${name}-downloadPdf`
+ })
+ }
+
+ return (
+
+
+
+ {i18n("downloadPdf")}
+
+
+
+ )
+}
diff --git a/component/options/weixin.tsx b/component/options/weixin.tsx
index 9137c6f..a325770 100644
--- a/component/options/weixin.tsx
+++ b/component/options/weixin.tsx
@@ -1,6 +1,7 @@
import CssCode from "~component/items/cssCode"
import DownloadHtml from "~component/items/downloadHtml"
import DownloadMarkdown from "~component/items/downloadMarkdown"
+import DownloadPdf from "~component/items/downloadPdf"
import EditMarkdown from "~component/items/editMarkdown"
import ShowTag from "~component/items/showTag"
import { i18n } from "~tools"
@@ -14,6 +15,7 @@ export default function Weixin() {
+
)
}
diff --git a/contents/weixin.tsx b/contents/weixin.tsx
index 35a3435..6e696b4 100644
--- a/contents/weixin.tsx
+++ b/contents/weixin.tsx
@@ -1,3 +1,4 @@
+import html2pdf from "html2pdf.js"
import type {
PlasmoCSConfig,
PlasmoCSUIProps,
@@ -6,7 +7,6 @@ import type {
PlasmoGetStyle
} from "plasmo"
import { useEffect, type FC } from "react"
-import { v4 as uuidv4 } from "uuid"
import { useMessage } from "@plasmohq/messaging/hook"
import { useStorage } from "@plasmohq/storage/dist/hook"
@@ -17,7 +17,7 @@ import { useContent } from "~utils/editMarkdownHook"
import Turndown from "~utils/turndown"
export const config: PlasmoCSConfig = {
- matches: ["https://mp.weixin.qq.com/*"]
+ matches: ["https://mp.weixin.qq.com/s/*"]
}
const turndownService = Turndown()
@@ -69,8 +69,152 @@ const PlasmoOverlay: FC = ({ anchor }) => {
if (req.name == "weixin-downloadHtml") {
downloadHtml()
}
+ if (req.name == "weixin-downloadPdf") {
+ downloadPdf()
+ }
})
+ console.log(777, html2pdf)
+
+ function downloadPdf() {
+ // 获取文章内容和标题、作者、时间等元信息
+ var article = document.querySelector(".rich_media_content")
+ var title = document.querySelector(".rich_media_title")
+ var author = document.querySelector(".weui-wa-hotarea") // 文章作者
+ var publishTime = document.querySelector("#publish_time") // 文章时间
+
+ if (article) {
+ // 创建一个容器用于添加元信息
+ var metaInfoDiv = document.createElement("div")
+ metaInfoDiv.style.marginBottom = "20px"
+ metaInfoDiv.style.borderBottom = "1px solid #eee"
+ metaInfoDiv.style.paddingBottom = "15px"
+
+ // 标题
+ var titleElement = document.createElement("h1")
+ titleElement.innerText = title ? title?.innerText.trim() : "未命名文章"
+ titleElement.style.fontSize = "24px"
+ titleElement.style.marginBottom = "10px"
+ metaInfoDiv.appendChild(titleElement)
+
+ // 作者
+ if (author) {
+ var authorElement = document.createElement("p")
+ authorElement.innerText = "作者: " + author.innerText.trim()
+ authorElement.style.fontSize = "14px"
+ authorElement.style.margin = "5px 0"
+ metaInfoDiv.appendChild(authorElement)
+ }
+
+ // 时间
+ if (publishTime) {
+ var timeElement = document.createElement("p")
+ timeElement.innerText = "发布时间: " + publishTime.innerText.trim()
+ timeElement.style.fontSize = "14px"
+ timeElement.style.margin = "5px 0"
+ metaInfoDiv.appendChild(timeElement)
+ }
+
+ // 将元信息插入到文章内容的顶部
+ article.insertBefore(metaInfoDiv, article.firstChild)
+
+ // 添加防止图片分页的CSS样式
+ var style = document.createElement("style")
+ style.innerHTML = `
+ .rich_media_content img {
+ page-break-inside: avoid;
+ break-inside: avoid;
+ max-width: 100%;
+ height: auto;
+ }
+ .rich_media_content p, .rich_media_content div {
+ page-break-inside: avoid;
+ break-inside: avoid;
+ }
+ `
+ document.head.appendChild(style)
+
+ // 确保所有图片加载完成
+ let images = article.querySelectorAll("img")
+ let imagePromises = []
+
+ images.forEach(function (img) {
+ // 处理懒加载的图片,确保图片的真实 URL 被加载
+ if (img.dataset && img.dataset.src) {
+ img.src = img.dataset.src
+ }
+
+ // 通过跨域获取图片,并将图片转换为 base64 格式
+ imagePromises.push(
+ new Promise(function (resolve) {
+ var imgElement = new Image()
+ imgElement.crossOrigin = "Anonymous"
+ imgElement.src = img.src
+ imgElement.onload = function () {
+ var canvas = document.createElement("canvas")
+ canvas.width = imgElement.width
+ canvas.height = imgElement.height
+ var ctx = canvas.getContext("2d")
+ ctx.drawImage(imgElement, 0, 0)
+ img.src = canvas.toDataURL("image/jpeg") // 使用JPEG格式并压缩质量到70%
+ resolve()
+ }
+ imgElement.onerror = resolve // 即使图片加载失败,继续处理
+ })
+ )
+ })
+
+ // 确保图片加载完成后再导出PDF
+ Promise.all(imagePromises)
+ .then(function () {
+ // 使用文章标题作为文件名
+ var fileName = title
+ ? title.innerText.trim() + ".pdf"
+ : "WeChat_Article.pdf"
+
+ var opt = {
+ margin: 0.5,
+ filename: fileName,
+ image: {
+ type: "jpeg",
+ quality: 1 // 降低图片质量以减小PDF体积
+ },
+ html2canvas: {
+ scale: 1.5, // 降低渲染比例以减小PDF体积
+ useCORS: true, // 允许跨域图片
+ logging: false // 关闭日志
+ // 可以根据需要添加其他html2canvas选项
+ },
+ jsPDF: {
+ unit: "in",
+ format: "a4", // 使用A4格式,比letter更常用且体积可能更小
+ orientation: "portrait"
+ },
+ pagebreak: {
+ mode: ["avoid-all", "css", "legacy"]
+ } // 遵循CSS中的page-break规则
+ }
+
+ // 使用 html2pdf 将文章内容导出为 PDF
+ html2pdf()
+ .from(article)
+ .set(opt)
+ .save()
+ .then(function () {})
+ .catch(function (error) {
+ alert("导出过程中出现问题: " + error.message)
+ console.log(error)
+ })
+ })
+ .catch(function (error) {
+ alert("处理图片时出现问题: " + error.message)
+ console.log(error)
+ })
+ } else {
+ alert("未找到文章内容")
+ }
+ }
+
function downloadMarkdown() {
const html = document.querySelector("#img-content")
const markdown = turndownService.turndown(html)
diff --git a/package.json b/package.json
index 02acfda..5ba0418 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "code-box",
"displayName": "__MSG_extensionName__",
- "version": "0.9.14",
+ "version": "0.9.15",
"description": "__MSG_extensionDescription__",
"author": "027xiguapi. <458813868@qq.com>",
"scripts": {
@@ -33,6 +33,7 @@
"dayjs": "^1.11.12",
"file-saver": "^2.0.5",
"html2canvas": "^1.4.1",
+ "html2pdf.js": "^0.10.2",
"jspdf": "^2.5.2",
"jssha": "^3.3.1",
"plasmo": "0.89.4",