@forge-kit/plugin-qr-code 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/main.tsx ADDED
@@ -0,0 +1,30 @@
1
+ import {StrictMode} from 'react'
2
+ import ReactDOM from "react-dom/client";
3
+ import {definePlugin} from '@forge-kit/types'
4
+ import {App} from '@/App.tsx'
5
+
6
+ let rootInstance: ReturnType<typeof ReactDOM.createRoot> | null = null;
7
+
8
+ const plugin = definePlugin({
9
+ bundleId: "com.forge-kit.plugin.qr-code",
10
+ name: '二维码生成与解析工具',
11
+ icon: `${import.meta.env.BASE_URL}icon.svg`,
12
+ description: "二维码生成与解析工具",
13
+ mount: (container, props = {}) => {
14
+ rootInstance = ReactDOM.createRoot(container);
15
+ rootInstance.render(
16
+ <StrictMode>
17
+ <App {...props}/>
18
+ </StrictMode>,
19
+ )
20
+ },
21
+ unmount: () => {
22
+ if (!rootInstance) return
23
+ rootInstance.unmount();
24
+ rootInstance = null;
25
+ }
26
+ });
27
+ if (import.meta.env.DEV) plugin.mount(document.getElementById('root')!)
28
+
29
+ export default plugin
30
+
@@ -0,0 +1,85 @@
1
+ import jsQR from 'jsqr'
2
+ import QRCode from 'qrcode'
3
+ import type {QRCodeErrorCorrectionLevel} from 'qrcode'
4
+
5
+ export const QR_ERROR_CORRECTION_LEVEL_OPTIONS: QRCodeErrorCorrectionLevel[] = ['L', 'M', 'Q', 'H']
6
+
7
+ export interface GenerateQrOptions {
8
+ width: number
9
+ margin: number
10
+ errorCorrectionLevel: QRCodeErrorCorrectionLevel
11
+ }
12
+
13
+ export const generateQrDataUrl = async (content: string, options: GenerateQrOptions): Promise<string> => {
14
+ return QRCode.toDataURL(content, options)
15
+ }
16
+
17
+ const getDecode2dContext = (width: number, height: number): {
18
+ context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D
19
+ width: number
20
+ height: number
21
+ } => {
22
+ if (typeof OffscreenCanvas !== 'undefined') {
23
+ const offscreenCanvas = new OffscreenCanvas(width, height)
24
+ const context = offscreenCanvas.getContext('2d', {willReadFrequently: true})
25
+ if (!context) throw new Error('无法创建 Canvas 上下文')
26
+ return {context, width, height}
27
+ }
28
+
29
+ const canvas = document.createElement('canvas')
30
+ canvas.width = width
31
+ canvas.height = height
32
+
33
+ const context = canvas.getContext('2d', {willReadFrequently: true})
34
+ if (!context) throw new Error('无法创建 Canvas 上下文')
35
+ return {context, width: canvas.width, height: canvas.height}
36
+ }
37
+
38
+ export const decodeQrFromImageUrl = async (imageUrl: string): Promise<string> => {
39
+ const img = await new Promise<HTMLImageElement>((resolve, reject) => {
40
+ const image = new Image()
41
+ image.onload = () => resolve(image)
42
+ image.onerror = () => reject(new Error('图片加载失败'))
43
+ image.src = imageUrl
44
+ })
45
+
46
+ const {context, width, height} = getDecode2dContext(img.naturalWidth, img.naturalHeight)
47
+
48
+ context.drawImage(img, 0, 0)
49
+ const imageData = context.getImageData(0, 0, width, height)
50
+
51
+ const result = jsQR(imageData.data, imageData.width, imageData.height, {
52
+ inversionAttempts: 'attemptBoth',
53
+ })
54
+
55
+ if (!result?.data) {
56
+ throw new Error('未识别到二维码,请尝试更清晰的图片')
57
+ }
58
+
59
+ return result.data
60
+ }
61
+
62
+ export const getImageFileFromFileList = (files: FileList | null): File | null => {
63
+ if (!files || files.length === 0) return null
64
+ for (const file of files) {
65
+ if (file.type.startsWith('image/')) return file
66
+ }
67
+ return null
68
+ }
69
+
70
+ export const getImageFileFromClipboard = (clipboardData: DataTransfer | null): File | null => {
71
+ if (!clipboardData) return null
72
+ for (const item of clipboardData.items) {
73
+ if (item.kind === 'file' && item.type.startsWith('image/')) {
74
+ return item.getAsFile()
75
+ }
76
+ }
77
+ return null
78
+ }
79
+
80
+ export const downloadDataUrl = (dataUrl: string, filename: string) => {
81
+ const link = document.createElement('a')
82
+ link.href = dataUrl
83
+ link.download = filename
84
+ link.click()
85
+ }