diff --git a/src/core/QRCodeStyling.ts b/src/core/QRCodeStyling.ts index 269fd8e4..6315b15a 100644 --- a/src/core/QRCodeStyling.ts +++ b/src/core/QRCodeStyling.ts @@ -6,10 +6,9 @@ import drawTypes from "../constants/drawTypes"; import defaultOptions, { RequiredOptions } from "./QROptions"; import sanitizeOptions from "../tools/sanitizeOptions"; -import { FileExtension, QRCode, Options, DownloadOptions, ExtensionFunction, Window } from "../types"; +import { FileExtension, QRCode, Options, DownloadOptions, ExtensionFunction, Window, NodeCanvasElement } from "../types"; import qrcode from "qrcode-generator"; import getMimeType from "../tools/getMimeType"; -import { Canvas as NodeCanvas, Image } from "canvas"; declare const window: Window; @@ -18,7 +17,7 @@ export default class QRCodeStyling { _window: Window; _container?: HTMLElement; _domCanvas?: HTMLCanvasElement; - _nodeCanvas?: NodeCanvas; + _nodeCanvas?: NodeCanvasElement; _svg?: SVGElement; _qr?: QRCode; _extension?: ExtensionFunction; @@ -79,7 +78,7 @@ export default class QRCodeStyling { const image64 = `data:${getMimeType('svg')};base64,${svg64}`; if (this._options.nodeCanvas?.loadImage) { - return this._options.nodeCanvas.loadImage(image64).then((image: Image) => { + return this._options.nodeCanvas.loadImage(image64).then((image) => { // fix blurry svg image.width = this._options.width; image.height = this._options.height; diff --git a/src/core/QRSVG.ts b/src/core/QRSVG.ts index b02ee7c4..565cdc56 100644 --- a/src/core/QRSVG.ts +++ b/src/core/QRSVG.ts @@ -7,8 +7,7 @@ import QRCornerDot, { availableCornerDotTypes } from "../figures/cornerDot/QRCor import { RequiredOptions } from "./QROptions"; import gradientTypes from "../constants/gradientTypes"; import shapeTypes from "../constants/shapeTypes"; -import { DotType, QRCode, FilterFunction, Gradient, Window } from "../types"; -import { Image } from "canvas"; +import { DotType, QRCode, FilterFunction, Gradient, Window, NodeCanvasImage } from "../types"; const squareMask = [ [1, 1, 1, 1, 1, 1, 1], @@ -40,7 +39,7 @@ export default class QRSVG { _cornersDotClipPath?: SVGElement; _options: RequiredOptions; _qr?: QRCode; - _image?: HTMLImageElement | Image; + _image?: HTMLImageElement | NodeCanvasImage; _imageUri?: string; _instanceId: number; @@ -457,7 +456,7 @@ export default class QRSVG { if (options.nodeCanvas?.loadImage) { options.nodeCanvas .loadImage(options.image) - .then((image: Image) => { + .then((image) => { this._image = image; if (this._options.imageOptions.saveAsBlob) { const canvas = options.nodeCanvas?.createCanvas( this._image.width, this._image.height); diff --git a/src/types/index.ts b/src/types/index.ts index 9f9153d4..777c98c4 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,6 +1,3 @@ -import { DOMWindow, JSDOM } from "jsdom"; -import nodeCanvas from "canvas"; - export interface UnknownObject { // eslint-disable-next-line @typescript-eslint/no-explicit-any [key: string]: any; @@ -14,7 +11,44 @@ export type GradientType = "radial" | "linear"; export type DrawType = "canvas" | "svg"; export type ShapeType = "square" | "circle"; -export type Window = DOMWindow; +// Minimal window-like interface — compatible with both browser Window and jsdom DOMWindow +export interface BrowserWindow { + document: Document; + XMLSerializer: typeof XMLSerializer; + Image: { new(): HTMLImageElement }; + XMLHttpRequest: typeof XMLHttpRequest; + FileReader: typeof FileReader; +} + +export type Window = BrowserWindow; + +// Minimal node-canvas interfaces — avoids importing the "canvas" package in browser bundles +export interface NodeCanvasImage { + width: number; + height: number; +} + +export interface NodeCanvasRenderingContext2D { + drawImage(image: NodeCanvasImage, dx: number, dy: number): void; +} + +export interface NodeCanvasElement { + width: number; + height: number; + getContext(contextId: "2d"): NodeCanvasRenderingContext2D | null; + toBuffer(mimeType: string): Buffer; + toDataURL(type?: string): string; +} + +export interface NodeCanvasFactory { + createCanvas(width: number, height: number): NodeCanvasElement; + loadImage(src: string): Promise; +} + +// Minimal jsdom constructor interface — avoids importing "jsdom" in browser bundles +export interface JSDOMConstructor { + new(html: string, options?: { resources?: string }): { window: BrowserWindow }; +} export type Gradient = { type: GradientType; @@ -116,8 +150,8 @@ export type Options = { margin?: number; data?: string; image?: string; - nodeCanvas?: typeof nodeCanvas; - jsdom?: typeof JSDOM; + nodeCanvas?: NodeCanvasFactory; + jsdom?: JSDOMConstructor; qrOptions?: { typeNumber?: TypeNumber; mode?: Mode;