生成二维码海报

This commit is contained in:
fzk
2025-02-19 14:57:53 +08:00
parent b584765ba1
commit a8aeea3925
5 changed files with 281 additions and 54 deletions
+5 -33
View File
@@ -13,42 +13,14 @@ chrome.runtime.onInstalled.addListener(function (object) {
chrome.runtime.requestUpdateCheck(function (status, details) {
if (status === "update_available") {
console.log("有更新可用!版本" + details.version)
chrome.action.setBadgeBackgroundColor({ color: "#fc5430" })
chrome.action.setBadgeText({
text: "升级"
})
chrome.runtime.reload()
// chrome.action.setBadgeBackgroundColor({ color: "#fc5430" })
// chrome.action.setBadgeText({
// text: "升级"
// })
// chrome.runtime.reload()
} else if (status === "no_update") {
console.log("没有可用更新。")
} else if (status === "throttled") {
console.log("更新检查被限流。")
}
})
chrome.tabs.onUpdated.addListener((tabId, _, tab) => {
// console.log(tabId, _, tab)
// if (!("sidePanel" in chrome)) {
// return
// }
//
// void (async () => {
// if (!tab.url) {
// return
// }
// // const url = new URL(tab.url)
// // if (
// // url.origin === ""
// // ) {
// // await chrome.sidePanel.setOptions({
// // tabId,
// // // path: "pages/options.html",
// // enabled: true
// // })
// // } else {
// // await chrome.sidePanel.setOptions({
// // tabId,
// // enabled: false
// // })
// // }
// })()
})
+73 -12
View File
@@ -5,16 +5,16 @@ import type {
PlasmoGetShadowHostId,
PlasmoGetStyle
} from "plasmo"
import { useEffect, useRef, type FC } from "react"
import qrcodeUrl from "raw:~/public/wx/qrcode_wx.jpg"
import React, { useEffect, useRef, useState, type FC } from "react"
import { useMessage } from "@plasmohq/messaging/hook"
import { useStorage } from "@plasmohq/storage/dist/hook"
import TagBtnStyle from "~component/tagBtn/style"
import Tags from "~component/ui/tags"
import { i18n, saveHtml, saveMarkdown } from "~tools"
import useCssCodeHook from "~utils/cssCodeHook"
import { useEditMarkdown } from "~utils/editMarkdownHook"
import makerQRPost from "~utils/makerQRPost"
import { useParseMarkdown } from "~utils/parseMarkdownHook"
import { Print } from "~utils/print"
import Turndown from "~utils/turndown"
@@ -61,15 +61,44 @@ const HOST_ID = "codebox-juejin"
export const getShadowHostId: PlasmoGetShadowHostId = () => HOST_ID
export const getOverlayAnchor: PlasmoGetOverlayAnchor = async () =>
document.querySelector("article.article .article-title")
document.querySelector("#juejin")
export const getStyle: PlasmoGetStyle = () => TagBtnStyle()
const style = {
box: {
position: "fixed" as const,
border: "1px solid #D9DADC",
left: "25px",
top: "85px",
width: "140px",
padding: "16px",
cursor: "pointer"
},
close: {
position: "absolute" as const,
top: "-5px",
right: "0px",
background: "none",
border: "none",
fontSize: "1.5rem",
cursor: "pointer",
padding: "0.5rem"
},
img: {
width: "100%"
},
item: {
color: "#000000",
fontSize: "1.2rem",
marginBottom: "3px"
}
}
const PlasmoOverlay: FC<PlasmoCSUIProps> = ({ anchor }) => {
const [parseContent, setParseContent] = useParseMarkdown()
const [showTag, setShowTag] = useStorage<boolean>("juejin-showTag", true)
const [cssCode, runCss] = useCssCodeHook("juejin")
const [content, setContent] = useEditMarkdown()
const [isShow, setIsShow] = useState(true)
useMessage(async (req, res) => {
if (req.name == "juejin-isShow") {
@@ -89,6 +118,13 @@ const PlasmoOverlay: FC<PlasmoCSUIProps> = ({ anchor }) => {
}
})
function getDescription() {
const summary = document.querySelector<HTMLMetaElement>(
'meta[name="description"]'
).content
summary && prompt("文章摘要:", summary)
}
function downloadPdf() {
const article = document.querySelector<HTMLElement>("article.article")
if (article) {
@@ -119,13 +155,38 @@ const PlasmoOverlay: FC<PlasmoCSUIProps> = ({ anchor }) => {
setParseContent(dom)
}
return showTag ? (
<Tags
onEdit={editMarkdown}
onDownload={downloadMarkdown}
onPrint={downloadPdf}
onParse={parseMarkdown}
/>
function onClose() {
setIsShow(false)
}
return showTag && isShow ? (
<div id="ws_cmbm" className="ws_cmbmc" style={style.box}>
<button style={style.close} onClick={onClose} aria-label="Close">
×
</button>
<img src={qrcodeUrl} alt="qrcodeUrl" style={style.img} />
<div style={style.item}>
<a onClick={getDescription}>文章摘要</a>
</div>
<div style={style.item}>
<a onClick={editMarkdown}>编辑markdown</a>
</div>
<div style={style.item}>
<a onClick={downloadMarkdown}>下载markdown</a>
</div>
<div style={style.item}>
<a onClick={downloadPdf}>下载PDF</a>
</div>
<div style={style.item}>
<a onClick={parseMarkdown}>解析markdown</a>
</div>
<div style={style.item}>
<a onClick={() => makerQRPost()}>生成海报</a>
</div>
<a style={style.item} href="https://www.code-box.fun" target="_blank">
帮助
</a>
</div>
) : (
<></>
)
+6 -7
View File
@@ -13,9 +13,10 @@ import React, { useEffect, useState, type FC } from "react"
import { useMessage } from "@plasmohq/messaging/hook"
import { useStorage } from "@plasmohq/storage/dist/hook"
import { i18n, saveHtml, saveMarkdown } from "~tools"
import { saveHtml, saveMarkdown } from "~tools"
import useCssCodeHook from "~utils/cssCodeHook"
import { useEditMarkdown } from "~utils/editMarkdownHook"
import makerQRPost from "~utils/makerQRPost"
import { useParseMarkdown } from "~utils/parseMarkdownHook"
import { Print } from "~utils/print"
import Turndown from "~utils/turndown"
@@ -139,8 +140,6 @@ const style = {
}
}
console.log(8878878)
const PlasmoOverlay: FC<PlasmoCSUIProps> = ({ anchor }) => {
const [parseContent, setParseContent] = useParseMarkdown()
const [showTag, setShowTag] = useStorage<boolean>("weixin-showTag", true)
@@ -320,10 +319,10 @@ const PlasmoOverlay: FC<PlasmoCSUIProps> = ({ anchor }) => {
<div style={style.item}>
<a onClick={() => downloadImages()}>下载所有图片</a>
</div>
<a
style={{ color: "#000" }}
href="https://www.code-box.fun"
target="_blank">
<div style={style.item}>
<a onClick={() => makerQRPost()}>生成海报</a>
</div>
<a style={style.item} href="https://www.code-box.fun" target="_blank">
帮助
</a>
</div>
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "code-box",
"displayName": "__MSG_extensionName__",
"version": "1.1.1",
"version": "1.1.2",
"description": "__MSG_extensionDescription__",
"author": "027xiguapi. <458813868@qq.com>",
"scripts": {
@@ -32,12 +32,12 @@
"antd": "^5.21.1",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.12",
"file-save": "^0.2.0",
"file-saver": "^2.0.5",
"html2canvas": "^1.4.1",
"jssha": "^3.3.1",
"jszip": "^3.10.1",
"plasmo": "0.89.4",
"qrcode": "^1.5.4",
"react": "18.2.0",
"react-dom": "18.2.0",
"uuid": "^10.0.0"
+195
View File
@@ -0,0 +1,195 @@
import { saveAs } from "file-saver"
import QRCode from "qrcode"
interface Position {
x: number
y: number
}
export default function makerQRCodeImg() {
const qrcodepostmaker = document.createElement("canvas")
qrcodepostmaker.id = "qrcodepostmaker"
qrcodepostmaker.style.display = "none"
document.body.appendChild(qrcodepostmaker)
// 文本换行处理
const textComputer = (
text: string,
style: string,
width: number,
ctx: CanvasRenderingContext2D
): string[] => {
if (text.replace(/\s/g, "").length === 0) {
return []
}
ctx.font = style
let temp = 0
const row: string[] = []
for (let i = 0; i <= text.length; i++) {
if (ctx.measureText(text.substring(temp, i)).width >= width) {
row.push(text.substring(temp, i - 1))
temp = i - 1
} else if (i === text.length) {
row.push(text.substring(temp, i))
}
}
return row
}
// 绘制文本
const textWriter = (
textArr: string[],
Style: string,
align: CanvasTextAlign,
color: string,
borderColor: string,
fontSize: number,
lineHeight: number,
pos: Position,
ctx: CanvasRenderingContext2D
): Position => {
ctx.font = Style
ctx.textAlign = align
ctx.fillStyle = color
ctx.strokeStyle = borderColor
for (const text of textArr) {
pos.y += fontSize * lineHeight
ctx.fillText(text, pos.x, pos.y)
}
return pos
}
// 生成海报
const makerQRPost = (): void => {
const canvas = document.querySelector<HTMLCanvasElement>("#qrcodepostmaker")
const ctx = canvas.getContext("2d")
if (!ctx) return
const QRCodeData = ctx.getImageData(0, 0, canvas.width, canvas.height)
const title = document.title
const desc = document.head.querySelector('meta[name="description"]')
? document.head.querySelector<HTMLMetaElement>(
'meta[name="description"]'
)!.content
: ""
const cardWidth = 360
const lineHeight = 1.6
const margin = 36
const titleStyle = 'Bold 18px "Microsoft YaHei"'
const descStyle = '16px "Microsoft YaHei"'
const titleArray = textComputer(
title,
titleStyle,
cardWidth - margin * 2,
ctx
)
const descArray = textComputer(desc, descStyle, cardWidth - margin * 2, ctx)
const cardHeight =
margin * 2.5 +
18 * titleArray.length * lineHeight +
16 * descArray.length * lineHeight +
(descArray.length ? margin / 2 : 0) +
300
canvas.width = cardWidth
canvas.height = cardHeight
const myGradient = ctx.createLinearGradient(0, 0, 0, cardHeight)
myGradient.addColorStop(0, "#2980B9")
myGradient.addColorStop(0.5, "#6DD5FA")
myGradient.addColorStop(1, "#FFFFFF")
ctx.fillStyle = myGradient
ctx.fillRect(0, 0, cardWidth, cardHeight)
ctx.fillStyle = "#FFFFFF"
ctx.beginPath()
ctx.arc(margin * 0.4, cardHeight - margin * 5, margin, 0, Math.PI * 2, true)
ctx.arc(
cardWidth - margin * 0.4,
cardHeight - margin * 3,
margin * 0.8,
0,
Math.PI * 2,
true
)
ctx.fillRect(0, cardHeight - margin * 5, cardWidth / 2, margin * 5)
ctx.fillRect(
cardWidth / 2,
cardHeight - margin * 3,
cardWidth / 2,
margin * 3
)
ctx.fill()
const titleEnd = textWriter(
titleArray,
titleStyle,
"center",
"black",
"rgba(255, 255, 255, 0.6)",
18,
lineHeight,
{ x: cardWidth / 2, y: margin },
ctx
)
const descEnd = textWriter(
descArray,
descStyle,
"left",
"black",
"rgba(255, 255, 255, 0.6)",
16,
lineHeight,
{ x: margin, y: titleEnd.y + margin / 2 },
ctx
)
ctx.fillStyle = "white"
ctx.fillRect((cardWidth - 288) / 2, descEnd.y + margin - 24, 288, 288)
ctx.putImageData(QRCodeData, (cardWidth - 256) / 2, descEnd.y + margin)
textWriter(
["(长按识别二维码进行访问)"],
descStyle,
"center",
"rgba(0, 0, 0, 0.6)",
"rgba(255, 255, 255, 0.6)",
16,
lineHeight,
{ x: cardWidth / 2, y: descEnd.y + margin + 256 },
ctx
)
saveAs(canvas.toDataURL("image/png"), title + ".png")
qrcodepostmaker.parentNode?.removeChild(qrcodepostmaker)
}
let tryTimes = 30
const makeQRCode = window.setInterval(() => {
try {
QRCode.toCanvas(
document.getElementById("qrcodepostmaker"),
window.location.href,
{ width: 260, errorCorrectionLevel: "Q" },
(error) => {
if (error) {
console.log(error)
return
}
makerQRPost()
}
)
window.clearInterval(makeQRCode)
} catch (error) {
console.log(error)
tryTimes--
if (!tryTimes) {
window.clearInterval(makeQRCode)
alert("没能成功载入功能库,请刷新重试~")
}
}
}, 200)
}