label-printer 0.7.7 → 0.7.8
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/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +20 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +20 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/index.ts","../src/commands/Command.ts","../src/commands/CommandGroup.ts","../src/commands/tspl/index.ts","../src/commands/tspl/TSPLCommand.ts","../src/commands/tspl/commands/TSPLRawCommand.ts","../src/commands/tspl/commands/TSPLCommandGroup.ts","../src/commands/tspl/commands/TSPLVisualCommand.ts","../src/helpers/UnitUtils.ts","../src/helpers/ImageDataParser.ts","../src/helpers/ImageProcessor.ts","../src/helpers/ImageUtils.ts","../src/commands/tspl/commands/basic/TSPLBitmapCommand.ts","../src/commands/tspl/types.ts","../src/commands/tspl/commands/basic/TSPLTextCommand.ts","../src/commands/tspl/commands/basic/TSPLGapCommand.ts","../src/commands/tspl/commands/basic/TSPLSizeCommand.ts","../src/commands/tspl/commands/basic/TSPLCLSCommand.ts","../src/commands/tspl/commands/basic/TSPLDirectionCommand.ts","../src/commands/tspl/commands/basic/TSPLPrintCommand.ts","../src/commands/tspl/commands/basic/TSPLBarCommand.ts","../src/commands/tspl/commands/basic/TSPLQRCommand.ts","../src/commands/tspl/commands/basic/TSPLBlockCommand.ts","../src/commands/tspl/commands/basic/TSPLDownload.ts","../src/commands/tspl/commands/basic/TSPLDisplay.ts","../src/commands/tspl/commands/basic/TSPLDiagonal.ts","../src/commands/tspl/commands/basic/TSPLBarcodeCommand.ts","../src/helpers/QRCodeUtils.ts","../src/commands/tspl/TSPLCommandGenerator.ts","../src/printers/index.ts","../src/printers/Printer.ts","../src/helpers/StringUtils.ts","../src/helpers/USBUtils.ts","../src/helpers/NetworkDevice.ts","../src/helpers/BonjourUtils.ts","../src/printers/TSPLPrinter.ts","../src/printers/PrinterService.ts","../src/labels/index.ts","../src/labels/Printable.ts","../src/labels/Label.ts","../src/labels/fields/LabelField.ts","../src/labels/fields/Line.ts","../src/labels/fields/Text.ts","../src/labels/fields/BarCode.ts","../src/labels/fields/Image.ts","../src/labels/fields/QRCode.ts","../src/labels/fields/Table.ts"],"sourcesContent":["export { default as Command } from \"./Command\"\nexport { default as CommandGroup } from \"./CommandGroup\"\n\nexport type PrinterLanguage = \"tspl\"\nexport type UnitSystem = \"imperial\"|\"metric\"|\"dot\"\n\nexport * as tspl from \"./tspl\"\nexport * from \"./types\"","import Device from \"@/helpers/Device\"\n\n/**\n * Base implementation for all types of command\n * Represents a command to be send to the printer to execute, such as print\n */\nexport default abstract class Command {\n /**\n * Returns a string representation of the command\n */\n abstract get commandString(): string\n\n print(fn: (command: string) => void) {\n fn(this.commandString)\n }\n\n /**\n * Write the command data to a device\n * @param device Device to write to\n */\n async writeTo(device: Device): Promise<void> {\n await this.writeString(this.commandString, device)\n await this.terminateCommand(device)\n }\n\n /**\n * Byte representation of a newline\n */\n protected get commandTerminatorBytes(): Uint8Array {\n return new Uint8Array([10])\n }\n\n /**\n * Writes a string to a device\n * @param data String representation of data\n * @param device Device to write to\n */\n protected async writeString(data: string, device: Device): Promise<void> {\n await device.writeString(data)\n }\n\n /**\n * Writes bytes to a device. It will automatically end a command with @see{commandTerminatorBytes}\n * @param data Byte array to send\n * @param device Device to write to\n */\n protected async writeBytes(data: Uint8Array|ArrayBuffer, device: Device): Promise<void> {\n await device.writeData(data)\n }\n\n /**\n * Write the command terminator to the device\n * @param device \n */\n protected async terminateCommand(device: Device): Promise<void> {\n await this.writeBytes(this.commandTerminatorBytes, device)\n }\n}","import Device from \"@/helpers/Device\";\nimport Command from \"./Command\";\n\n/**\n * A utility class that helps grouping commands together\n * Should be implemented with a specific command type to ensure only commands for the same language are\n * grouped together\n */\nexport default abstract class CommandGroup<T extends Command> extends Command {\n private commands: T[]\n\n constructor(commands: T[]) {\n super()\n this.commands = commands\n }\n\n print(fn: (command: string) => void) {\n for (let commandIndex in this.commands) {\n this.commands[commandIndex].print(fn)\n }\n }\n\n async writeTo(device: Device): Promise<void> {\n for (let commandIndex in this.commands) {\n await this.commands[commandIndex].writeTo(device)\n }\n }\n\n get commandString(): string {\n return this.commands.map(c => c.commandString).join(\"\\n\")\n }\n}","export { default as TSPLCommand } from \"./TSPLCommand\"\nexport { default as commandGenerator } from \"./TSPLCommandGenerator\"\n\nexport * from \"./commands\"\nexport * from \"./types\"","import Command from \"@/commands/Command\";\n\n/**\n * Base for TSPL specific commands\n */\nexport default abstract class TSPLCommand extends Command {\n}","import TSPLCommand from \"../TSPLCommand\"\n\n/**\n * A raw TSPL command. Can be used to use a command that is not yet supported\n */\nexport default class TSPLRawCommand extends TSPLCommand {\n /**\n * Raw command string\n */\n private readonly commandBody: string\n\n /**\n * Initialize a command with a raw body\n * @param body\n */\n constructor(body: string) {\n super()\n this.commandBody = body\n }\n\n get commandString(): string {\n return this.commandBody;\n }\n}\n","import CommandGroup from \"@/commands/CommandGroup\";\nimport TSPLCommand from \"../TSPLCommand\";\n\n/**\n * Command group for tspl commands\n */\nexport default class TSPLCommandGroup extends CommandGroup<TSPLCommand> {}","import TSPLCommand from \"../TSPLCommand\";\n\n/**\n * Base for all TSPL commands that have a visual effect on the final label\n */\nexport default abstract class TSPLVisualCommand extends TSPLCommand {\n protected readonly x: number\n protected readonly y: number\n\n constructor(x: number, y: number) {\n super()\n this.x = x\n this.y = y\n }\n}","import { UnitSystem } from \"@/commands\"\n\nconst pointsPerInch = 72\n\nexport function getSizePreserveAspect(width: number, height: number, desiredWidth?: number, desiredHeight?: number) {\n // 0 width or height is not a valid number so we filter those dogether with undefined or null values\n if(desiredHeight && desiredWidth) {\n return { width: desiredWidth, height: desiredHeight }\n }\n if(desiredHeight) {\n const scaleFactor = desiredHeight / height\n return { width: width * scaleFactor, height: desiredHeight }\n } else if (desiredWidth) {\n const scaleFactor = desiredWidth / width\n return { width: desiredWidth, height: height * scaleFactor }\n } else {\n return { width, height }\n }\n}\n\nexport function valueWithUnit(value: number, unitSystem: UnitSystem) {\n switch(unitSystem) {\n case \"dot\": return `${value} dot`\n case \"imperial\": return value\n case \"metric\": return `${value} mm`\n }\n}\n\n/**\n * Convert a value from dots in points in a given dpi\n */\nexport function dotToPoint(dots: number, dpi: number): number {\n const inch = dots / dpi\n return Math.round(inch * pointsPerInch)\n}\n\n/**\n * Converts the points value to dots\n * 1 inch = 72 points (standard in typography)\n * Formula: dots = points * dpi / pointsPerInch\n * @param points \n * @param dpi \n * @returns \n */\nexport function pointsToDots(points: number, dpi: number): number {\n const pointsPerInch = 72;\n const dots = points * dpi / pointsPerInch;\n return dots;\n}","\n\nexport interface ImageData {\n width: number;\n height: number;\n data: Uint8Array;\n bitsPerPixel: number;\n}\n\nexport function parsePNG(buffer: Buffer): ImageData {\n const pngSignature = Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]);\n if (!buffer.subarray(0, 8).equals(pngSignature)) {\n throw new Error('Invalid PNG file');\n }\n\n let width = 0, height = 0, bitDepth = 0, colorType = 0;\n let compressionMethod = 0, filterMethod = 0, interlaceMethod = 0;\n let palette: Buffer | null = null;\n let transparency: Buffer | null = null; // <-- Add this\n let idatChunks: Buffer[] = [];\n\n let offset = 8;\n while (offset < buffer.length) {\n const chunkLength = buffer.readUInt32BE(offset);\n const chunkType = buffer.subarray(offset + 4, offset + 8).toString('ascii');\n const chunkData = buffer.subarray(offset + 8, offset + 8 + chunkLength);\n\n if (chunkType === 'IHDR') {\n width = chunkData.readUInt32BE(0);\n height = chunkData.readUInt32BE(4);\n bitDepth = chunkData.readUInt8(8);\n colorType = chunkData.readUInt8(9);\n compressionMethod = chunkData.readUInt8(10);\n filterMethod = chunkData.readUInt8(11);\n interlaceMethod = chunkData.readUInt8(12);\n } else if (chunkType === 'PLTE') {\n palette = chunkData;\n } else if (chunkType === 'tRNS') {\n transparency = chunkData;\n } else if (chunkType === 'IDAT') {\n idatChunks.push(chunkData);\n } else if (chunkType === 'IEND') {\n break;\n }\n offset += 8 + chunkLength + 4; // chunk header + data + CRC\n }\n\n if (compressionMethod !== 0) throw new Error('Unsupported PNG compression method');\n if (filterMethod !== 0) throw new Error('Unsupported PNG filter method');\n if (interlaceMethod !== 0) throw new Error('Interlaced PNGs not supported');\n if (idatChunks.length === 0) throw new Error('No image data found in PNG');\n\n const compressedData = Buffer.concat(idatChunks);\n let decompressedData: Buffer;\n try {\n const zlib = require('zlib');\n decompressedData = zlib.inflateSync(compressedData);\n } catch (error) {\n throw new Error('Failed to decompress PNG data: ' + error);\n }\n\n if (bitDepth !== 8) throw new Error('Only 8-bit PNGs are supported in this parser');\n\n let bytesPerPixel: number;\n let channels: number;\n let outputChannels = 4;\n switch (colorType) {\n case 0: channels = 1; bytesPerPixel = 1; break; // Grayscale\n case 2: channels = 3; bytesPerPixel = 3; break; // RGB\n case 3: channels = 1; bytesPerPixel = 1; break; // Palette\n case 4: channels = 2; bytesPerPixel = 2; break; // Grayscale+Alpha\n case 6: channels = 4; bytesPerPixel = 4; break; // RGBA\n default: throw new Error(`Unsupported PNG color type: ${colorType}`);\n }\n\n const scanlineLength = width * bytesPerPixel;\n const data = new Uint8Array(width * height * outputChannels);\n\n // PNG filters are applied relative to the *unfiltered* previous scanline.\n // Keep the previous unfiltered scanline buffer to decode correctly.\n let prevUnfilteredScanline: Buffer = Buffer.alloc(scanlineLength);\n\n for (let y = 0; y < height; y++) {\n const scanlineStart = y * (scanlineLength + 1);\n const filterType = decompressedData[scanlineStart];\n const scanline = decompressedData.subarray(scanlineStart + 1, scanlineStart + 1 + scanlineLength);\n\n const unfilteredScanline = applyPNGFilter(filterType, scanline, prevUnfilteredScanline, bytesPerPixel);\n prevUnfilteredScanline = unfilteredScanline as Buffer;\n\n for (let x = 0; x < width; x++) {\n const outIdx = (y * width + x) * outputChannels;\n\n if (colorType === 0) { // Grayscale\n const gray = unfilteredScanline[x];\n data[outIdx] = gray;\n data[outIdx + 1] = gray;\n data[outIdx + 2] = gray;\n data[outIdx + 3] = 255;\n } else if (colorType === 2) { // RGB\n data[outIdx] = unfilteredScanline[x * 3];\n data[outIdx + 1] = unfilteredScanline[x * 3 + 1];\n data[outIdx + 2] = unfilteredScanline[x * 3 + 2];\n data[outIdx + 3] = 255;\n } else if (colorType === 3) { // Palette\n if (!palette) throw new Error('Palette PNG missing PLTE chunk');\n const idx = unfilteredScanline[x];\n data[outIdx] = palette[idx * 3];\n data[outIdx + 1] = palette[idx * 3 + 1];\n data[outIdx + 2] = palette[idx * 3 + 2];\n data[outIdx + 3] = transparency && idx < transparency.length ? transparency[idx] : 255;\n } else if (colorType === 4) { // Grayscale + Alpha\n const gray = unfilteredScanline[x * 2];\n data[outIdx] = gray;\n data[outIdx + 1] = gray;\n data[outIdx + 2] = gray;\n data[outIdx + 3] = unfilteredScanline[x * 2 + 1];\n } else if (colorType === 6) { // RGBA\n data[outIdx] = unfilteredScanline[x * 4];\n data[outIdx + 1] = unfilteredScanline[x * 4 + 1];\n data[outIdx + 2] = unfilteredScanline[x * 4 + 2];\n data[outIdx + 3] = unfilteredScanline[x * 4 + 3];\n }\n }\n }\n\n return {\n data,\n width,\n height,\n bitsPerPixel: outputChannels\n };\n}\n/**\n * Apply PNG filter to scanline\n * @param filterType PNG filter type (0-4)\n * @param scanline Current scanline data\n * @param prevScanline Previous scanline data\n * @param bytesPerPixel Bytes per pixel\n * @returns Unfiltered scanline\n */\nfunction applyPNGFilter(filterType: number, scanline: Buffer, prevScanline: Buffer, bytesPerPixel: number): Buffer {\n const result = Buffer.alloc(scanline.length);\n\n for (let i = 0; i < scanline.length; i++) {\n let filtered = scanline[i];\n let a = i >= bytesPerPixel ? result[i - bytesPerPixel] : 0; // Left pixel\n let b = prevScanline[i] || 0; // Above pixel\n let c = (i >= bytesPerPixel && prevScanline[i - bytesPerPixel]) ? prevScanline[i - bytesPerPixel] : 0; // Above-left pixel\n \n switch (filterType) {\n case 0: // None\n result[i] = filtered;\n break;\n case 1: // Sub\n result[i] = (filtered + a) & 0xFF;\n break;\n case 2: // Up\n result[i] = (filtered + b) & 0xFF;\n break;\n case 3: // Average\n result[i] = (filtered + Math.floor((a + b) / 2)) & 0xFF;\n break;\n case 4: // Paeth\n const p = a + b - c;\n const pa = Math.abs(p - a);\n const pb = Math.abs(p - b);\n const pc = Math.abs(p - c);\n let paeth;\n if (pa <= pb && pa <= pc) {\n paeth = a;\n } else if (pb <= pc) {\n paeth = b;\n } else {\n paeth = c;\n }\n result[i] = (filtered + paeth) & 0xFF;\n break;\n default:\n result[i] = filtered;\n }\n }\n\n return result;\n}\n","/**\n * Cross-platform image processing utility that works in both browser and Node.js environments\n * Replaces the need for the 'image-pixels' package\n * Supports local files, data URLs, Blobs, and remote URLs\n */\nimport { ImageData, parsePNG } from './ImageDataParser';\n\nexport class ImageProcessor {\n /**\n * Get pixel information about an image\n * @param image Image to process (local file path, remote URL, data URL, or Blob)\n * @param target Optional target raster size. Useful for vector inputs (e.g. SVG) to rasterize at the final size.\n * @returns Promise with image data including width, height, pixel data, and bits per pixel\n */\n static async getImageData(image: string | Blob, target?: { width: number; height: number }): Promise<ImageData> {\n if (typeof window !== 'undefined') {\n return this.getImageDataBrowser(image, target);\n } else {\n return this.getImageDataNode(image, target);\n }\n }\n\n /******** BROWSER ********/\n\n /**\n * Get pixel information about an image in browser environment\n * @param image Image to process\n * @param target Optional target raster size.\n * @returns Promise with image data\n */\n private static async getImageDataBrowser(image: string | Blob, target?: { width: number; height: number }): Promise<ImageData> {\n const loadImage = (src: string): Promise<HTMLImageElement> => {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.crossOrigin = 'anonymous';\n img.onload = () => resolve(img);\n img.onerror = () => reject(new Error('Failed to load image'));\n img.src = src;\n });\n }\n\n let src: string\n let revokeUrl: string | undefined\n\n if (typeof image === 'string') {\n src = this.normalizePotentialSVGSource(image)\n } else {\n revokeUrl = URL.createObjectURL(image)\n src = revokeUrl\n }\n\n try {\n const img = await loadImage(src)\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n\n if (!ctx) {\n throw new Error('Could not get canvas context')\n }\n\n const width = target?.width ?? img.width\n const height = target?.height ?? img.height\n\n canvas.width = width;\n canvas.height = height;\n\n ctx.drawImage(img, 0, 0, width, height);\n const imageData = ctx.getImageData(0, 0, width, height);\n\n return {\n data: new Uint8Array(imageData.data),\n width,\n height,\n bitsPerPixel: 4,\n }\n } finally {\n if (revokeUrl) URL.revokeObjectURL(revokeUrl)\n }\n }\n\n /******** NODEJS ********/\n\n /**\n * Get pixel information about an image in Node.js environment\n * @param image Image to process\n * @param target Optional target raster size.\n * @returns Promise with image data\n */\n private static async getImageDataNode(image: string | Blob, _target?: { width: number; height: number }): Promise<ImageData> {\n console.log('Processing image in Node.js environment');\n // For Node.js, we'll use a simple approach with built-in modules\n if (image instanceof Blob) {\n throw new Error('Blob input not supported in Node.js environment. Use file path or data URL instead.');\n }\n\n const trimmed = image.trim()\n if (trimmed.startsWith('<svg')) {\n return this.rasterizeSVGNode(trimmed, _target)\n }\n \n // Check if it's a data URL\n if (image.startsWith('data:')) {\n return this.getImageFromData(image, _target);\n } else if (image.startsWith('http://') || image.startsWith('https://')) {\n return this.getImageFromUrl(image, _target);\n } else {\n return this.getImageFromFile(image, _target);\n }\n }\n\n /**\n * Parse a data URL to extract image data\n * @param dataURL Data URL string\n * @returns Promise with image data\n */\n private static async getImageFromData(dataURL: string, target?: { width: number; height: number }): Promise<ImageData> {\n const [header, data] = dataURL.split(',');\n const mimeType = header.match(/data:([^;]+)/)?.[1];\n \n if (!mimeType?.startsWith('image/')) {\n throw new Error('Invalid image data URL');\n }\n \n const extension = mimeType.split('/')[1].toLowerCase();\n if (extension === 'svg+xml' || mimeType === 'image/svg+xml') {\n const isBase64 = header.includes(';base64')\n const svgText = isBase64\n ? Buffer.from(data, 'base64').toString('utf8')\n : decodeURIComponent(data)\n return this.rasterizeSVGNode(svgText, target)\n }\n\n const buffer = Buffer.from(data, 'base64');\n return this.parse(buffer, extension);\n }\n\n /**\n * Image data from file\n * @param image \n * @returns \n */\n private static async getImageFromFile(image: string, target?: { width: number; height: number }): Promise<ImageData> {\n const fs = await eval(\"require\")('fs');\n const path = await eval(\"require\")('path');\n \n if (!fs.existsSync(image)) {\n throw new Error(`Image file not found: ${image}`);\n }\n \n const buffer = fs.readFileSync(image);\n const ext = path.extname(image).toLowerCase();\n\n if (ext === '.svg') {\n const svgText = buffer.toString('utf8')\n return this.rasterizeSVGNode(svgText, target)\n }\n\n return this.parse(buffer, ext);\n }\n\n /**\n * Fetch and process a remote image in Node.js environment\n * @param url Remote image URL\n * @returns Promise with image data\n */\n private static async getImageFromUrl(url: string, target?: { width: number; height: number }): Promise<ImageData> {\n // Use dynamic import to support both Node.js versions\n let fetch: any;\n try {\n // Try to use built-in fetch (Node.js 18+)\n fetch = globalThis.fetch;\n } catch {\n // Use https module as fallback\n return this.fetchWithHttps(url, target);\n }\n\n if (!fetch) {\n return this.fetchWithHttps(url, target);\n }\n\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch image: ${response.status} ${response.statusText}`);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n const buffer = Buffer.from(arrayBuffer);\n \n // Determine image type from content or URL\n const contentType = response.headers.get('content-type');\n const imageType = this.getImageType(contentType || '', url);\n\n if (imageType === 'svg') {\n const svgText = buffer.toString('utf8')\n return this.rasterizeSVGNode(svgText, target)\n }\n\n return this.parse(buffer, imageType);\n }\n\n /**\n * Fetch remote image using Node.js https module (fallback)\n * @param url Remote image URL\n * @returns Promise with image data\n */\n private static async fetchWithHttps(url: string, target?: { width: number; height: number }): Promise<ImageData> {\n const https = await eval(\"require\")('https');\n const http = await eval(\"require\")('http');\n \n return new Promise((resolve, reject) => {\n const client = url.startsWith('https:') ? https : http;\n \n const request = client.get(url, (response: any) => {\n if (response.statusCode !== 200) {\n reject(new Error(`Failed to fetch image: ${response.statusCode} ${response.statusMessage}`));\n return;\n }\n \n const chunks: Buffer[] = [];\n \n response.on('data', (chunk: any) => {\n chunks.push(chunk);\n });\n \n response.on('end', () => {\n try {\n const buffer = Buffer.concat(chunks);\n \n // Determine image type from content-type header or URL\n const contentType = response.headers['content-type'] || '';\n const imageType = this.getImageType(contentType || '', url);\n\n if (imageType === 'svg') {\n const svgText = buffer.toString('utf8')\n resolve(this.rasterizeSVGNode(svgText, target))\n return\n }\n\n resolve(this.parse(buffer, imageType))\n } catch (error) {\n reject(error);\n }\n });\n \n response.on('error', (error: any) => {\n reject(error);\n });\n });\n \n request.on('error', (error: any) => {\n reject(new Error(`Failed to fetch remote image: ${error.message}`));\n });\n \n request.setTimeout(30000, () => {\n request.destroy();\n reject(new Error('Request timeout: Failed to fetch remote image within 30 seconds'));\n });\n });\n }\n\n /**\n * Decide content type\n */\n private static getImageType(contentType: string, url: string): string {\n if (contentType) {\n if (contentType.includes('png')) {\n return 'png';\n } else if (contentType.includes('jpeg') || contentType.includes('jpg')) {\n return 'jpeg';\n } else if (contentType.includes('svg')) {\n return 'svg';\n }\n }\n \n const urlLower = url.toLowerCase();\n if (urlLower.includes('.png')) {\n return 'png';\n } else if (urlLower.includes('.jpg') || urlLower.includes('.jpeg')) {\n return 'jpeg';\n } else if (urlLower.includes('.svg')) {\n return 'svg';\n }\n\n return \"\"\n }\n\n /**\n * Parse image data by extension\n */\n private static parse(buffer: Buffer, extension: string): ImageData {\n const normalizedExtension = extension.startsWith(\".\") ? extension.slice(1) : extension\n console.log(`Parsing image with extension: ${normalizedExtension}`);\n\n if (normalizedExtension === 'png') {\n return parsePNG(buffer);\n } else if (normalizedExtension === 'jpeg' || normalizedExtension === 'jpg') {\n return this.parseJPEG(buffer);\n } else if (normalizedExtension === 'svg') {\n // Note: In Node we don't reach this when loading SVG through the high-level APIs because we route\n // SVG through rasterizeSVGNode() first. Keeping this as a guard.\n throw new Error('svg-not-supported-in-node')\n } else {\n throw new Error(`Unsupported image format: ${normalizedExtension}. Supported formats: PNG, JPEG`);\n }\n }\n\n private static rasterizeSVGNode(svg: string, target?: { width: number; height: number }): ImageData {\n // TODO: This is Node-only. For best browser-safety this likely benefits from conditional exports so\n // browser bundlers don't attempt to include @resvg/resvg-js.\n let Resvg: any\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n Resvg = eval(\"require\")(\"@resvg/resvg-js\").Resvg\n } catch (_e) {\n throw new Error('svg-rasterizer-missing')\n }\n\n const fitTo = target\n ? { mode: 'width' as const, value: target.width }\n : undefined\n\n const resvg = new Resvg(svg, {\n fitTo,\n })\n\n const pngData: Uint8Array = resvg.render().asPng()\n const pngBuffer = Buffer.from(pngData)\n const imageData = parsePNG(pngBuffer)\n\n if (target && (imageData.width !== target.width || imageData.height !== target.height)) {\n return this.resize(imageData, target.width, target.height)\n }\n\n return imageData\n }\n\n private static normalizePotentialSVGSource(source: string): string {\n const trimmed = source.trim()\n const isInlineSvg = trimmed.startsWith('<svg')\n const isSvgDataUrl = trimmed.startsWith('data:image/svg+xml')\n\n if (isInlineSvg) {\n const encoded = encodeURIComponent(trimmed)\n return `data:image/svg+xml;charset=utf-8,${encoded}`\n }\n\n if (isSvgDataUrl) return source\n return source\n }\n\n private static parseJPEG(buffer: Buffer): ImageData {\n // JPEG signature check\n if (buffer[0] !== 0xFF || buffer[1] !== 0xD8) {\n throw new Error('Invalid JPEG file');\n }\n \n let offset = 2;\n let width = 0;\n let height = 0;\n \n // Look for SOF (Start of Frame) marker to get dimensions\n while (offset < buffer.length - 1) {\n if (buffer[offset] === 0xFF) {\n const marker = buffer[offset + 1];\n \n // SOF0, SOF1, SOF2 markers\n if (marker >= 0xC0 && marker <= 0xC2) {\n height = buffer.readUInt16BE(offset + 5);\n width = buffer.readUInt16BE(offset + 7);\n break;\n }\n \n // Skip to next marker\n if (offset + 2 < buffer.length) {\n const segmentLength = buffer.readUInt16BE(offset + 2);\n offset += 2 + segmentLength;\n } else {\n break;\n }\n } else {\n offset++;\n }\n }\n \n if (width === 0 || height === 0) {\n throw new Error('Could not determine JPEG dimensions');\n }\n \n // Create a meaningful placeholder pattern instead of random noise\n // This creates a gradient pattern that represents the image structure\n const pixelCount = width * height;\n const data = new Uint8Array(pixelCount * 4); // RGBA format\n \n // Calculate average color from file data for base color\n let avgR = 0, avgG = 0, avgB = 0;\n const sampleSize = Math.min(1000, buffer.length);\n for (let i = 0; i < sampleSize; i += 3) {\n avgR += buffer[i] || 0;\n avgG += buffer[i + 1] || 0;\n avgB += buffer[i + 2] || 0;\n }\n avgR = Math.floor(avgR / (sampleSize / 3));\n avgG = Math.floor(avgG / (sampleSize / 3));\n avgB = Math.floor(avgB / (sampleSize / 3));\n \n // Create a gradient pattern based on position and average colors\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const i = (y * width + x) * 4;\n \n // Create a gradient pattern\n const xRatio = x / width;\n const yRatio = y / height;\n \n // Mix the average color with a gradient\n const r = Math.floor(avgR * (0.5 + 0.5 * xRatio));\n const g = Math.floor(avgG * (0.5 + 0.5 * yRatio));\n const b = Math.floor(avgB * (0.5 + 0.5 * (xRatio + yRatio) / 2));\n \n data[i] = Math.min(255, Math.max(0, r)); // R\n data[i + 1] = Math.min(255, Math.max(0, g)); // G\n data[i + 2] = Math.min(255, Math.max(0, b)); // B\n data[i + 3] = 255; // A\n }\n }\n \n return {\n data,\n width,\n height,\n bitsPerPixel: 4\n };\n }\n\n /**\n * Convert image data to grayscale\n * @param imageData Original image data\n * @returns Grayscale image data\n */\n static toGrayscale(imageData: ImageData): ImageData {\n const { data, width, height } = imageData;\n const grayscaleData = new Uint8Array(data.length);\n \n for (let i = 0; i < data.length; i += 4) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const a = data[i + 3];\n \n // Calculate grayscale using luminance formula\n const gray = Math.round(0.299 * r + 0.587 * g + 0.114 * b);\n \n grayscaleData[i] = gray; // R\n grayscaleData[i + 1] = gray; // G\n grayscaleData[i + 2] = gray; // B\n grayscaleData[i + 3] = a; // A (preserve alpha)\n }\n \n return {\n data: grayscaleData,\n width,\n height,\n bitsPerPixel: imageData.bitsPerPixel\n };\n }\n\n /**\n * Resize image data (simple nearest neighbor algorithm)\n * @param imageData Original image data\n * @param newWidth Target width\n * @param newHeight Target height\n * @returns Resized image data\n */\n static resize(imageData: ImageData, newWidth: number, newHeight: number): ImageData {\n const { data, width, height, bitsPerPixel } = imageData;\n const resizedData = new Uint8Array(newWidth * newHeight * bitsPerPixel);\n \n const xRatio = width / newWidth;\n const yRatio = height / newHeight;\n \n for (let y = 0; y < newHeight; y++) {\n for (let x = 0; x < newWidth; x++) {\n const srcX = Math.floor(x * xRatio);\n const srcY = Math.floor(y * yRatio);\n \n const srcIndex = (srcY * width + srcX) * bitsPerPixel;\n const destIndex = (y * newWidth + x) * bitsPerPixel;\n \n for (let c = 0; c < bitsPerPixel; c++) {\n resizedData[destIndex + c] = data[srcIndex + c];\n }\n }\n }\n \n return {\n data: resizedData,\n width: newWidth,\n height: newHeight,\n bitsPerPixel\n };\n }\n}\n\nexport default ImageProcessor;\n","import { getSizePreserveAspect } from \"./UnitUtils\"\nimport ImageProcessor from \"./ImageProcessor\"\n\n/**\n * Helper type to transmit image bitmap data\n */\nexport type Pixels = {\n data: Uint8Array, \n width: number,\n height: number, \n bitsPerPixel: number\n}\n\nexport type BitmapLike = {\n width: number,\n height: number,\n bytes: Uint8Array\n}\n\n/**\n * Helper type to transmit black and white bitmap data\n */\nexport type BWBitmap = BitmapLike\n\nconst BLACK_PIXEL = 0\nconst WHITE_PIXEL = 1\nconst DEFAULT_THRESHOLD = 240\nconst DEFAULT_CROP_ALPHA_THRESHOLD = 16\n\n/**\n * Set of image utility\n */\nexport default class ImageUtils {\n /**\n * Get pixel information about an image\n * @param image Image to process\n * @param target Optional target raster size. Useful for vector inputs (e.g. SVG) to rasterize at the final size.\n * @returns \n */\n static async getPixels(image: string|Blob, target?: { width: number; height: number }): Promise<Pixels> {\n return await ImageProcessor.getImageData(image, target)\n }\n\n /**\n * Return a bitmap in which all pixels are represented with one bit of either 1 or 0 representing white and black\n * pixels respectively. `destinationWidth` and `destinationHeight` have to be smaller or equal to the\n * input size as only downscaling is performed\n * \n * @param image Image to process \n * @param destinationWidth Width of the output bitmap\n * @param destinationHeight Height of the output bitmap\n * @returns \n */\n static async getBWBitmap(\n image: string|Blob,\n destinationWidth?: number,\n destinationHeight?: number,\n threshold?: number,\n lsbFirst: boolean = false,\n ): Promise<BWBitmap> {\n const {\n data,\n width,\n height,\n bitsPerPixel\n } = await this.getPixels(\n image,\n destinationWidth != null && destinationHeight != null\n ? { width: destinationWidth, height: destinationHeight }\n : undefined\n )\n\n // Auto-crop transparent margins for RGBA sources so content isn't shrunk to a few pixels when resizing.\n // Only applies when alpha channel is present.\n let cropX0 = 0\n let cropY0 = 0\n let cropX1 = width - 1\n let cropY1 = height - 1\n\n if (bitsPerPixel > 3) {\n let found = false\n let minX = width\n let minY = height\n let maxX = -1\n let maxY = -1\n\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const a = data[(y * width * bitsPerPixel) + (x * bitsPerPixel) + 3]\n if (a >= DEFAULT_CROP_ALPHA_THRESHOLD) {\n found = true\n if (x < minX) minX = x\n if (y < minY) minY = y\n if (x > maxX) maxX = x\n if (y > maxY) maxY = y\n }\n }\n }\n\n if (found) {\n cropX0 = minX\n cropY0 = minY\n cropX1 = maxX\n cropY1 = maxY\n }\n }\n\n const cropWidth = cropX1 - cropX0 + 1\n const cropHeight = cropY1 - cropY0 + 1\n \n const dim = getSizePreserveAspect(cropWidth, cropHeight, destinationWidth, destinationHeight)\n // Number of pixels width and height => number of bits for each row and number of rows\n const dWidth = dim.width\n const dHeight = dim.height\n \n const differenceToDividable = dWidth % 8 == 0 ? 0 : (8 - (dWidth % 8))\n const dividableDWidth = dWidth + differenceToDividable\n\n // Luminance buffer for adaptive thresholding.\n // Stored per destination pixel (including padding), 0..255.\n const luminances = new Uint8Array(dividableDWidth * dHeight)\n\n let destinationIndex = 0\n for (let h=0; h < dHeight; h++) {\n const srcY0 = cropY0 + Math.floor((h * cropHeight) / dHeight)\n const srcY1 = Math.max(srcY0, cropY0 + Math.floor(((h + 1) * cropHeight) / dHeight) - 1)\n\n for(let w=0; w < dWidth; w++) {\n const srcX0 = cropX0 + Math.floor((w * cropWidth) / dWidth)\n const srcX1 = Math.max(srcX0, cropX0 + Math.floor(((w + 1) * cropWidth) / dWidth) - 1)\n\n let lumSum = 0\n let count = 0\n let opaqueCount = 0\n let opaqueLumSum = 0\n let opaqueWeightSum = 0\n let minOpaqueLum = 255\n\n for (let sy = srcY0; sy <= srcY1; sy++) {\n for (let sx = srcX0; sx <= srcX1; sx++) {\n const baseIndex = (sy * width * bitsPerPixel) + (sx * bitsPerPixel)\n\n const r = data[baseIndex]\n const g = data[baseIndex + 1]\n const b = data[baseIndex + 2]\n const a = bitsPerPixel > 3 ? data[baseIndex + 3] : 255\n\n // Composite onto white background first (important for antialiasing and transparent pixels)\n const alpha = a / 255\n const rC = r * alpha + 255 * (1 - alpha)\n const gC = g * alpha + 255 * (1 - alpha)\n const bC = b * alpha + 255 * (1 - alpha)\n\n lumSum += (0.299 * rC) + (0.587 * gC) + (0.114 * bC)\n count += 1\n\n if (a > 0) {\n opaqueCount += 1\n const lum = (0.299 * r) + (0.587 * g) + (0.114 * b)\n opaqueLumSum += lum * alpha\n opaqueWeightSum += alpha\n if (lum < minOpaqueLum) minOpaqueLum = lum\n }\n }\n }\n\n const avgLum = count > 0 ? (lumSum / count) : 255\n const avgOpaqueLum = opaqueWeightSum > 0 ? (opaqueLumSum / opaqueWeightSum) : 255\n const opaqueRatio = count > 0 ? (opaqueCount / count) : 0\n const luminance = opaqueCount === 0\n ? 255\n : (opaqueRatio < 0.25 ? minOpaqueLum : avgOpaqueLum)\n luminances[destinationIndex] = Math.max(0, Math.min(255, Math.round(luminance)))\n\n destinationIndex += 1\n }\n \n for(let i=0; i < differenceToDividable; i++) {\n luminances[destinationIndex] = 255\n destinationIndex += 1\n }\n }\n\n const thresholdValue = threshold ?? this.otsuThreshold(luminances, dWidth, dividableDWidth, dHeight)\n\n // Size of the array has to be with * height but width has to be extended to be dividable by 8\n const bitmapData = new Uint8Array(dividableDWidth * dHeight)\n for (let h = 0; h < dHeight; h++) {\n const rowOffset = h * dividableDWidth\n for (let w = 0; w < dividableDWidth; w++) {\n const idx = rowOffset + w\n bitmapData[idx] = luminances[idx] > thresholdValue ? WHITE_PIXEL : BLACK_PIXEL\n }\n }\n \n const byteArrays = this.chunk(bitmapData,8)\n const widthInBytes = dividableDWidth / 8\n \n const bytes = byteArrays.map((b) => this.bitsToByte(b, lsbFirst))\n const finalBytes = new Uint8Array(bytes)\n \n return {\n width: widthInBytes,\n height: dHeight,\n bytes: finalBytes\n }\n }\n\n private static otsuThreshold(luminances: Uint8Array, contentWidth: number, rowWidth: number, height: number): number {\n // Histogram of 0..255\n const hist = new Uint32Array(256)\n let total = 0\n\n for (let y = 0; y < height; y++) {\n const rowOffset = y * rowWidth\n for (let x = 0; x < contentWidth; x++) {\n hist[luminances[rowOffset + x]] += 1\n total += 1\n }\n }\n\n if (total === 0) return DEFAULT_THRESHOLD\n\n let sum = 0\n for (let t = 0; t < 256; t++) sum += t * hist[t]\n\n let sumB = 0\n let wB = 0\n let wF = 0\n let maxBetween = -1\n let threshold = DEFAULT_THRESHOLD\n\n for (let t = 0; t < 256; t++) {\n wB += hist[t]\n if (wB === 0) continue\n wF = total - wB\n if (wF === 0) break\n\n sumB += t * hist[t]\n\n const mB = sumB / wB\n const mF = (sum - sumB) / wF\n const between = wB * wF * (mB - mF) * (mB - mF)\n\n if (between > maxBetween) {\n maxBetween = between\n threshold = t\n }\n }\n\n return threshold\n }\n\n /**\n * Splits an array into chunks.\n * @param originalArray\n * @param chunkSize\n * @returns\n */\n private static chunk(originalArray: Uint8Array, chunkSize: number): Uint8Array[] {\n const resultArray = [];\n\n for (let i = 0; i < originalArray.length; i += chunkSize) {\n const chunk = originalArray.slice(i, i + chunkSize);\n resultArray.push(chunk);\n }\n\n return resultArray;\n }\n\n /**\n * Converts an array of bits to a byte\n * @param bits\n * @returns\n */\n private static bitsToByte(bits: Uint8Array, lsbFirst: boolean) {\n let byteValue = 0\n\n if (lsbFirst) {\n for (let i = 0; i < bits.length; i++) {\n byteValue |= (bits[i] & 1) << i\n }\n return byteValue\n }\n\n for (let i = 0; i < bits.length; i++) {\n byteValue = (byteValue << 1) | (bits[i] & 1)\n }\n return byteValue\n }\n\n static dilateBWBitmap(bitmap: BWBitmap, iterations: number = 1): BWBitmap {\n let current = bitmap\n for (let i = 0; i < iterations; i++) {\n current = this.dilateOnce(current)\n }\n return current\n }\n\n static bwBitmapToPBM(bitmap: BWBitmap, widthDots?: number): Uint8Array {\n const widthBytes = bitmap.width\n const height = bitmap.height\n const widthBits = widthDots ?? (widthBytes * 8)\n const header = `P4\\n${widthBits} ${height}\\n`\n\n const headerBytes = new TextEncoder().encode(header)\n\n // PBM P4 expects 1=black, 0=white, MSB-first in each byte.\n // Our BWBitmap uses 0=black, 1=white. So we invert bits.\n const rowBytes = Math.ceil(widthBits / 8)\n const out = new Uint8Array(headerBytes.length + rowBytes * height)\n out.set(headerBytes, 0)\n\n const src = bitmap.bytes\n let offset = headerBytes.length\n\n for (let y = 0; y < height; y++) {\n const rowStart = y * widthBytes\n for (let xb = 0; xb < rowBytes; xb++) {\n const b = src[rowStart + xb] ?? 0xff\n out[offset++] = (~b) & 0xff\n }\n\n // If widthDots is not byte-aligned, clear the unused bits in the last byte.\n const extraBits = (rowBytes * 8) - widthBits\n if (extraBits > 0) {\n const mask = 0xff << extraBits\n out[offset - 1] = out[offset - 1] & mask\n }\n }\n\n return out\n }\n\n static async saveBWBitmapAsPBM(bitmap: BWBitmap, filePath: string, widthDots?: number): Promise<void> {\n if (typeof window !== \"undefined\") {\n throw new Error(\"pbm-export-not-supported-in-browser\")\n }\n\n const fs = await eval(\"require\")(\"fs\")\n const bytes = this.bwBitmapToPBM(bitmap, widthDots)\n fs.writeFileSync(filePath, bytes)\n }\n\n private static dilateOnce(bitmap: BWBitmap): BWBitmap {\n const widthBytes = bitmap.width\n const widthBits = widthBytes * 8\n const height = bitmap.height\n\n const src = bitmap.bytes\n const dst = new Uint8Array(src.length)\n\n const getBit = (x: number, y: number): 0|1 => {\n if (x < 0 || y < 0 || x >= widthBits || y >= height) return 1\n const byteIndex = (y * widthBytes) + (x >> 3)\n const bitIndex = 7 - (x & 7)\n return ((src[byteIndex] >> bitIndex) & 1) as 0|1\n }\n\n const setBit = (x: number, y: number, value: 0|1) => {\n if (x < 0 || y < 0 || x >= widthBits || y >= height) return\n const byteIndex = (y * widthBytes) + (x >> 3)\n const mask = 1 << (7 - (x & 7))\n if (value === 1) dst[byteIndex] |= mask\n else dst[byteIndex] &= (~mask) & 0xff\n }\n\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < widthBits; x++) {\n // We represent black as 0, white as 1.\n const isBlack = (\n getBit(x, y) === 0 ||\n getBit(x - 1, y) === 0 ||\n getBit(x + 1, y) === 0 ||\n getBit(x, y - 1) === 0 ||\n getBit(x, y + 1) === 0 ||\n getBit(x - 1, y - 1) === 0 ||\n getBit(x + 1, y - 1) === 0 ||\n getBit(x - 1, y + 1) === 0 ||\n getBit(x + 1, y + 1) === 0\n )\n setBit(x, y, isBlack ? 0 : 1)\n }\n }\n\n return {\n width: widthBytes,\n height,\n bytes: dst,\n }\n }\n}","import ImageUtils, { BWBitmap } from \"@/helpers/ImageUtils\";\nimport { GraphicMode } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\nimport Device from \"@/helpers/Device\";\n\n/**\n * Represents a bitmap command. Can be used to draw an image to the label\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLBitmapCommand extends TSPLVisualCommand {\n /**\n * Bitmap to present. \n * TSPL only supports black and write printing so this bitmap contains a matrix of 1 (White pixel)\n * and 0 (Black pixel) values\n */\n private readonly bitmap: BWBitmap\n private readonly mode: GraphicMode\n\n /**\n * @param bitmap Bitmap to present. \n * @param x X coordinates in dots\n * @param y Y Coordinates in dots\n * @param mode Represents the strategy to use when two bitmaps overlap. The final value will be determined by\n * either overwriting the first bitmap's value with the second one or performing an 'or' or 'xor' operation on the values\n */\n constructor(bitmap: BWBitmap, x: number, y: number, mode?: GraphicMode) {\n super(x, y);\n this.bitmap = bitmap;\n this.mode = mode ?? \"overwrite\"\n }\n\n get commandString(): string {\n const textDecoder = new TextDecoder('utf-8')\n const bytesString = textDecoder.decode(this.bitmap.bytes)\n\n return `${this.commandWithoutBytes}${bytesString.slice(0,5)}...\\n`;\n }\n\n private get commandWithoutBytes(): string {\n return `BITMAP ${this.x}, ${this.y},${this.bitmap.width},${this.bitmap.height},${this.modeValue},`\n }\n\n private get modeValue(): 0|1|2 {\n switch (this.mode) {\n case \"overwrite\": return 0\n case \"or\": return 1\n case \"xor\": return 2\n }\n }\n\n async writeTo(device: Device): Promise<void> {\n await this.writeString(this.commandWithoutBytes, device)\n await this.writeBytes(this.bitmap.bytes, device)\n await this.terminateCommand(device)\n }\n\n /**\n * Create a new bitmap command for the given image url\n * @param image Image to create command for \n * @param x X coordinate of the image\n * @param y Y coordinate of the image\n * @param imageWidth Desired width of the image\n * @param imageHeight Desired height of the image\n * @param mode Graphics mode\n * @returns \n */\n static async forImageUrl(image: string, x: number, y: number, imageWidth?: number, imageHeight?: number, mode?: GraphicMode) {\n const bitmap = await ImageUtils.getBWBitmap(image, imageWidth, imageHeight)\n return new TSPLBitmapCommand(bitmap, x, y, mode)\n }\n}","export type Rotation = 0|90|180|270\nexport type Alignment = undefined|\"left\"|\"center\"|\"right\"\n\n/**\n * Convert an alignemnt string to its number value\n * @param alignment \n * @returns \n */\nexport const alignmentToNumber = (alignment: Alignment): 0|1|2|3 => {\n switch(alignment) {\n case undefined: return 0\n case \"left\": return 1\n case \"center\": return 2\n case \"right\": return 3\n }\n}\n\n/**\n * Represents the strategy to use when two bitmaps overlap. The final value will be determined by\n * either overwriting the first bitmap's value with the second one or performing an 'or' or 'xor' operation\n * on the values\n */\nexport type GraphicMode = \"overwrite\"|\"or\"|\"xor\"\nexport type LabelDirection = \"normal\"|\"inverse\"\nexport type ECCLevel = \"L\"|\"M\"|\"Q\"|\"H\"\nexport type AutoManual = \"A\"|\"M\"\nexport type QRModel = \"M1\"|\"M2\"\nexport type BarcodeType = \"CODE128\"|\"EAN13\"|\"EAN8\"|\"EAN5\"|\"EAN2\"|\"UPC\"|\"CODE39\"|\"ITF14\"|\"MSI10\"|\"MSI11\"|\"MSI1010\"|\"MSI1110\"|\"pharmacode\"|\"codabar\"\nexport type BarcodeHumanReable = \"none\"|\"left\"|\"right\"|\"center\"","import { Alignment, Rotation, alignmentToNumber } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Prints a single line text on the label\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLTextCommand extends TSPLVisualCommand {\n /**\n * Name of the font to use. Consult documentation for more info\n */\n protected readonly font: string\n /**\n * Angle of rotation of the text. 0, 90, 180 or 270\n */\n protected readonly rotatation: Rotation\n /**\n * Multiplication of the font size in x axis\n */\n protected readonly xMultiplication: number\n /**\n * Multiplication of the font size in y axis\n */\n protected readonly yMultiplication: number\n /**\n * Text alignment. Left, Center or Right. The default alignmnet is left\n */\n protected readonly alignment: number\n /**\n * Text to print\n */\n protected readonly content: string\n\n constructor(content: string, x: number, y: number, font: string, rotation?: Rotation, xMultiplication?: number, yMultiplication?: number, alignment?: Alignment) {\n super(x, y)\n this.font = font\n this.rotatation = rotation ?? 0\n this.xMultiplication = xMultiplication ?? 1\n this.yMultiplication = yMultiplication ?? 1\n this.alignment = alignmentToNumber(alignment)\n this.content = content\n }\n\n get commandString(): string {\n return `TEXT ${this.x},${this.y},\\\"${this.font}\\\",${this.rotatation},${this.xMultiplication},${this.yMultiplication},${this.alignment},\\\"${this.content}\\\"`\n }\n}","import { valueWithUnit } from \"@/helpers/UnitUtils\";\nimport TSPLCommand from \"../../TSPLCommand\";\nimport { UnitSystem } from \"@/commands\";\n\n/**\n * Defines the gap between two labels\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLGapCommand extends TSPLCommand {\n private readonly gap: number\n private readonly offset: number\n\n /**\n * This controls what unit the {@link width} and {@link height} will be\n * - For imperial, the unit is inches\n * - For metric, the unit is milimeters\n * - For dots, the unit is dots\n */\n private readonly unitSystem: UnitSystem\n\n constructor(gap: number, offset: number, unitSystem: UnitSystem) {\n super()\n this.gap = gap\n this.offset = offset\n this.unitSystem = unitSystem\n } \n\n get commandString(): string {\n return `GAP ${valueWithUnit(this.gap, this.unitSystem)}, ${valueWithUnit(this.offset, this.unitSystem)}`\n }\n}","import { valueWithUnit } from \"@/helpers/UnitUtils\";\nimport TSPLCommand from \"../../TSPLCommand\";\nimport { UnitSystem } from \"@/commands\";\n\n/**\n * Defines the size of the label to rpint\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLSizeCommand extends TSPLCommand {\n private readonly width: number\n private readonly height: number\n /**\n * This controls what unit the {@link width} and {@link height} will be\n * - For imperial, the unit is inches\n * - For metric, the unit is milimeters\n * - For dots, the unit is dots\n */\n private readonly unitSystem: UnitSystem\n\n constructor(width: number, height: number, unitSystem: UnitSystem) {\n super()\n this.width = width\n this.height = height\n this.unitSystem = unitSystem\n } \n\n get commandString(): string {\n return `SIZE ${valueWithUnit(this.width, this.unitSystem)}, ${valueWithUnit(this.height, this.unitSystem)}`\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\n\n/**\n * Clear the image buffer\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLCLSCommand extends TSPLCommand {\n get commandString(): string {\n return \"CLS\"\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\nimport { LabelDirection } from \"../../types\";\n\n/**\n * This command defines in which direction will the label be printed and wether or not to mirror the image\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLDirectionCommand extends TSPLCommand {\n private readonly direction: 0|1\n private readonly mirror: 0|1\n\n /**\n * @param direction Controls the orientation of the resulting label compared to the printer\n * @param mirror Controls mirroring relative to the center line of the label perpendicular to the printhead. See the documentsion for examples\n */\n constructor(direction: LabelDirection, mirror?: boolean) {\n super()\n this.direction = direction == \"normal\" ? 1 : 0\n this.mirror = mirror ? 1 : 0\n }\n\n get commandString(): string {\n return `DIRECTION ${this.direction}, ${this.mirror}`\n }\n}\n","import TSPLCommand from \"../../TSPLCommand\";\n\n/**\n * Prints the current image buffer\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLPrintCommand extends TSPLCommand {\n /**\n * The number of set to print.\n */\n private readonly sets: number\n /**\n * The number of copies to print of each set.\n * The difference between a set and a copy is that if you have a counter for example,\n * the counter will be incremented for each set but not for each copy\n */\n private readonly copies: number\n\n constructor(sets: number, copies: number = 1) {\n super()\n this.sets = sets\n this.copies = copies\n }\n\n get commandString(): string {\n return `PRINT ${this.sets}, ${this.copies}`\n }\n}","import TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Draws a black bar\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLBarCommand extends TSPLVisualCommand {\n private readonly width: number\n private readonly height: number\n\n /**\n * @param x X coordinates in dots\n * @param y Y coordinates in dots\n * @param width Width of tha bar in dots\n * @param height Height of the bar in dots\n */\n constructor(x: number, y: number, width: number, height: number) {\n super(x,y)\n this.width = width\n this.height = height\n }\n\n get commandString(): string {\n return `BAR ${this.x}, ${this.y}, ${this.width}, ${this.height}`\n }\n}","import { ECCLevel, AutoManual, Rotation, QRModel } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Prints a QR code\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLQRCommand extends TSPLVisualCommand {\n private readonly ecc: ECCLevel\n private readonly cellWidth: number\n private readonly mode: AutoManual\n private readonly rotation: Rotation\n private readonly model: QRModel\n /**\n * Should be between 0 and 7\n */\n private readonly mask: number\n private readonly content: string\n\n constructor(content: string, \n x: number, \n y: number, \n cellWidth: number, \n ecc: ECCLevel = \"H\", \n mode: AutoManual = \"A\", \n rotation: Rotation = 0, \n model: QRModel = \"M2\", \n mask: number = 7) {\n super(x,y)\n this.content = content\n this.cellWidth = cellWidth\n this.ecc = ecc\n this.mode = mode\n this.rotation = rotation\n this.model = model\n this.mask = mask\n\n if (mask < 0 || mask > 8) {\n throw new Error(`Invalid mask provided: ${mask}`)\n }\n }\n\n get commandString(): string {\n return `QRCODE ${this.x}, ${this.y}, ${this.ecc}, ${this.cellWidth}, ${this.mode}, ${this.rotation}, ${this.model}, \\\"${this.content}\\\"`\n }\n}","import { Alignment, Rotation } from \"../../types\";\nimport TSPLTextCommand from \"./TSPLTextCommand\";\n\nexport default class TSPLBlockCommand extends TSPLTextCommand {\n private readonly width: number\n private readonly height: number\n private readonly lineSpacing: number\n\n constructor(content: string, \n x: number, \n y: number, \n width: number,\n height: number,\n font: string, \n rotation?: Rotation, \n xMultiplication?: number, \n yMultiplication?: number, \n lineSpacing: number = 0,\n alignment?: Alignment) {\n super(content, x, y, font, rotation, xMultiplication, yMultiplication, alignment)\n this.width = width\n this.height = height\n this.lineSpacing = lineSpacing\n }\n\n get commandString(): string {\n return `BLOCK ${this.x},${this.y},${this.width}, ${this.height},\\\"${this.font}\\\",${this.rotatation},${this.xMultiplication},${this.yMultiplication},${this.lineSpacing},${this.alignment},\\\"${this.content}\\\"`\n }\n}","import Device from \"@/helpers/Device\"\nimport TSPLCommand from \"../../TSPLCommand\"\n\ntype Data = ArrayBuffer|Uint8Array\n/**\n * A raw TSPL command. Can be used to use a command that is not yet supported\n */\nexport default class TSPLDownload extends TSPLCommand {\n /**\n * Name of the file on the printer\n */\n private readonly fileName: string\n private readonly data: Data\n\n /**\n * Initialize a command with a raw body\n * @param body\n */\n constructor(fileName: string, data: Data) {\n super()\n this.fileName = fileName\n this.data = data\n }\n\n get commandString(): string {\n return `DOWNLOAD \"${this.fileName}\", ${this.data.byteLength},`\n }\n\n async writeTo(device: Device): Promise<void> {\n await this.writeString(this.commandString, device)\n await this.writeBytes(this.data, device)\n await this.terminateCommand(device)\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\n\nexport type DisplayType = \"CLS\"|\"IMAGE\"|\"OFF\"\n\n/**\n * Displays the image buffer on the screen\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLDisplay extends TSPLCommand {\n private readonly type: DisplayType\n\n constructor(type: DisplayType) {\n super()\n this.type = type\n }\n\n get commandString(): string {\n return `DISPLAY ${this.type}`\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\nimport { Point } from \"@/commands\";\n\nexport default class TSPLDiagonal extends TSPLCommand {\n private readonly start: Point\n private readonly end: Point\n private readonly thickness: number\n\n constructor(start: Point, end: Point, thickness: number = 3) {\n super()\n this.start = start\n this.end = end\n this.thickness = thickness\n }\n\n get commandString(): string {\n return `DIAGONAL ${this.start.x}, ${this.start.y}, ${this.end.x}, ${this.end.y}, ${this.thickness}`\n }\n}","import { Alignment, BarcodeHumanReable, BarcodeType, Rotation, alignmentToNumber } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\n\nexport default class TSPLBarcodeCommand extends TSPLVisualCommand {\n private readonly type: BarcodeType\n private readonly height: number\n private readonly rotation: Rotation\n private readonly humanReadable: number\n private readonly narrow: number\n private readonly wide: number\n private readonly alignment: number\n private readonly content: string\n\n /**\n * @param x X coordinate in dots\n * @param y Y Coordinate in dots\n * @param type Type of the barcode\n * @param height Height of the barcode in dots\n * @param narrow Width of narrow elements in dots\n * @param wide Width of the wide elements in dots\n * @param content Content of the barcode. Supported content depends on the barcode type\n * @param rotation Rotation \n * @param alignment Alignment of the barcode\n */\n constructor(x: number, \n y: number, \n type: BarcodeType, \n height: number, \n narrow: number, \n wide: number,\n content: string,\n rotation: Rotation = 0, \n humanReadable: BarcodeHumanReable = \"left\",\n alignment: Alignment = \"left\") {\n super(x,y)\n this.type = type\n this.height = height\n this.narrow = narrow\n this.wide = wide\n this.content = content\n this.rotation = rotation\n this.humanReadable = TSPLBarcodeCommand.humanReadableValue(humanReadable)\n this.alignment = alignmentToNumber(alignment)\n }\n \n get commandString(): string {\n return `BARCODE ${this.x}, ${this.y}, \\\"${this.type}\\\", ${this.height}, ${this.humanReadable},${this.rotation}, ${this.narrow}, ${this.wide},${this.alignment}, \\\"${this.content}\\\"`\n }\n\n private static humanReadableValue(hr: BarcodeHumanReable): number {\n switch (hr) {\n case \"none\": return 0\n case \"left\": return 1\n case \"center\": return 2\n case \"right\": return 3\n }\n }\n}","// These mappings are for hight error correction level and for alpahnumeric data\n// The mapping has to be interpreted like this: up to (including) 10 characters, we have 21 cells\nexport const QRLengthMapping = {\n 10: 21,\n 20: 25,\n 35: 29,\n 50: 33,\n 64: 37,\n 84: 41,\n 93: 45,\n 122: 49,\n 143: 53,\n 174: 57,\n 200: 61,\n 227: 65,\n 259: 69,\n 283: 73,\n 321: 77,\n 365: 81,\n 408: 85,\n 452: 89,\n 493: 93,\n 557: 97,\n 587: 101,\n 640: 105,\n 672: 109,\n 744: 113,\n 779: 117,\n 864: 121,\n 910: 125,\n 958: 129,\n 1016: 133,\n 1080: 137,\n 1150: 141,\n 1226: 145,\n 1307: 149,\n 1394: 153,\n 1431: 157,\n 1530: 161,\n 1591: 165,\n 1658: 169,\n 1774: 173,\n 1852: 177\n}","import { BitmapLike } from \"@/helpers/ImageUtils\";\nimport { Point, UnitSystem } from \"..\";\nimport CommandGenerator from \"../CommandGenerator\";\nimport TSPLCommand from \"./TSPLCommand\";\nimport { TSPLBitmapCommand, TSPLCLSCommand, TSPLCommandGroup, TSPLDiagonal, TSPLDirectionCommand, TSPLDisplay, TSPLDownload, TSPLGapCommand, TSPLPrintCommand, TSPLQRCommand, TSPLRawCommand, TSPLSizeCommand, TSPLTextCommand } from \"./commands\";\nimport { Alignment, BarcodeHumanReable, BarcodeType, GraphicMode, LabelDirection, Rotation } from \"./types\";\nimport TSPLBarcodeCommand from \"./commands/basic/TSPLBarcodeCommand\";\nimport { QRLengthMapping } from \"@/helpers/QRCodeUtils\";\n\n/**\n * Command generator for tspl commands\n */\nclass TSPLCommandGenerator implements CommandGenerator<TSPLCommand> {\n commandGroup(commands: TSPLCommand[]) {\n return new TSPLCommandGroup(commands)\n }\n\n print(sets: number, copiesPerSet: number): TSPLCommand {\n return new TSPLPrintCommand(sets, copiesPerSet)\n }\n\n text(content: string, x: number, y: number, font: string|\"default\", size: number): TSPLCommand {\n const fontName = font == \"default\" ? \"0\" : font\n return new TSPLTextCommand(content, x, y, fontName, 0, size, size, \"left\")\n }\n\n upload(name: string, data: ArrayBuffer | Uint8Array): TSPLCommand {\n return new TSPLDownload(name, data)\n }\n\n setUp(width: number, height: number, gap: number, offset: number, direction: LabelDirection, mirror: boolean = false, unitSystem: UnitSystem): TSPLCommand {\n const commands = [\n new TSPLSizeCommand(width, height, unitSystem),\n new TSPLGapCommand(gap, offset, unitSystem),\n new TSPLDirectionCommand(direction, mirror),\n new TSPLCLSCommand()\n ]\n\n return new TSPLCommandGroup(commands)\n }\n\n display() {\n return new TSPLCommandGroup([\n new TSPLDisplay(\"CLS\"),\n new TSPLDisplay(\"IMAGE\")\n ])\n }\n\n line(start: Point, end: Point, thickness: number): TSPLCommand {\n return new TSPLDiagonal(start, end, thickness)\n }\n \n image(image: BitmapLike, x: number, y: number, mode?: GraphicMode | undefined): TSPLCommand {\n return new TSPLBitmapCommand(image, x, y, mode)\n }\n\n qrCode(content: string, width: number, x: number, y: number): TSPLCommand {\n const cellCount = this.cellCount(content)\n const cellWidth = Math.round(width / cellCount)\n // We start the content With A to indicate that our data is alphanumeric. \n // Not using auto ensures that we can easily calculate the cell with for a given content\n return new TSPLQRCommand(`A${content}`, x, y, cellWidth, 'H', \"M\")\n }\n \n barCode(content: string, x: number, y: number, type: BarcodeType, height: number, rotation: Rotation, humanReadable: BarcodeHumanReable, alignment: Alignment): TSPLCommand {\n return new TSPLBarcodeCommand(x, y, type, height, 1, 1, content, rotation, humanReadable, alignment)\n }\n\n private cellCount(content: string): number {\n const limits = Object.keys(QRLengthMapping).map( limit => Number(limit) ).sort((a, b) => a - b)\n const contentLength = content.length\n\n let i = 0\n while(limits[i] < contentLength && i < limits.length - 1) {\n i ++\n }\n\n return QRLengthMapping[limits[i] as keyof typeof QRLengthMapping]\n }\n}\n\nexport default new TSPLCommandGenerator()","export { default as Printer } from \"./Printer\"\nexport type { PrinterStatus } from \"./Printer\"\nexport { PrinterService } from \"./PrinterService\"","import { Command, PrinterLanguage } from \"@/commands\";\nimport { LabelDirection } from \"@/commands/tspl\";\nimport Device from \"@/helpers/Device\";\nimport { Label } from \"@/labels\"\n\nexport type PrinterStatus =\n | \"normal\"\n | \"head_opened\"\n | \"paper_jam\"\n | \"paper_jam_head_opened\"\n | \"out_of_paper\"\n | \"out_of_paper_head_opened\"\n | \"out_of_ribbon\"\n | \"out_of_ribbon_head_opened\"\n | \"out_of_ribbon_paper_jam\"\n | \"out_of_ribbon_paper_jam_head_opened\"\n | \"out_of_ribbon_out_of_paper\"\n | \"out_of_ribbon_out_of_paper_head_opened\"\n | \"paused\"\n | \"printing\"\n | \"other_error\"\n\n/**\n * Base class that encapsulates functionality of all printers\n */\nexport default abstract class Printer {\n protected readonly device: Device\n\n /**\n * Printer language used by the type of printer the subclass represents\n */\n abstract get language(): PrinterLanguage\n\n /**\n * When called, it will feed the labels to the beginig of the next label\n */\n abstract feedLabel(): Promise<void>\n\n abstract getModelname(): Promise<string>\n\n abstract getStatus(): Promise<PrinterStatus>\n\n constructor(device: Device) {\n this.device = device\n }\n\n /**\n * Close the printer USB\n */\n async close() {\n await this.device.close()\n }\n\n /**\n * Prints a label\n * @param label \n */\n async print(label: Label, \n sets: number,\n gap: number, \n copiesPerSet: number = 1,\n direction: LabelDirection = \"normal\",\n mirror: boolean = false, \n gapOffset: number = 0) {\n const commands = await label.fullPrintCommand(this.language, gap, direction, sets, copiesPerSet, mirror, gapOffset)\n await this.writeCommand(commands)\n }\n\n /**\n * Display label on the printer's screen\n * @param label \n */\n async display(label: Label, direction: LabelDirection = \"normal\", mirror: boolean = false) {\n const command = await label.fullDisplayCommand(this.language, direction, mirror)\n await this.writeCommand(command)\n }\n\n /**\n * Writes a command to the printers usb\n * @param command Command to send to the usb\n */\n async writeCommand(command: Command): Promise<void> {\n if(!this.device.opened) await this.device.openAndConfigure()\n await command.writeTo(this.device)\n }\n\n /**\n * Writes a raw string to the printer\n * @param text String to send to the printer\n */\n async writeRawString(text: string): Promise<void> {\n if(!this.device.opened) await this.device.openAndConfigure()\n await this.device.writeString(text)\n }\n\n /**\n * Check if the device is indeed a printer\n * @param device \n */\n static try(_device: Device): Promise<boolean> {\n throw new Error(\"try(device:) should be implemented\")\n }\n}","/**\n * Collection of helpers to work with strings\n */\nexport default class StringUtils {\n /**\n * Convert string to utf8 array\n * @param str Convert string to byte array\n */\n toUTF8Array(str: string) {\n let utf8Encode = new TextEncoder();\n return utf8Encode.encode(str)\n }\n\n /**\n * Convert bytes to utf8 encoded string\n * @param bytes Bytes to decode\n * @returns A string\n */\n toString(bytes: Uint8Array|DataView) {\n let decoder = new TextDecoder()\n return decoder.decode(bytes)\n }\n}\n\nexport const isWhitespace = (text: string) => text.trim() === \"\"","import StringUtils from \"./StringUtils\";\n\nconst unsupportedUsbError = \"usb-unsupported\"\nconst stringHelper = new StringUtils()\n\n export type UsbRequestFilter = {\n vendorId?: number\n productId?: number\n }\n\nlet usbAgent: USB\n\n/**\n * @returns The appropiate USB agent based on the environment\n */\nconst getUSB = async (): Promise<USB> => {\n if(usbAgent) return usbAgent\n\n if(typeof window !== \"undefined\") {\n if(navigator.usb) {\n usbAgent = navigator.usb\n } else {\n throw unsupportedUsbError\n }\n } else {\n // TODO: Check how to avoid eval\n const { WebUSB } = eval(\"require\")(\"usb\")\n usbAgent = new WebUSB({allowAllDevices: true})\n }\n\n return usbAgent\n}\n\n/**\n * Returns the list of available devices\n * In node this returns all the connected devices but in the browser it will only return devices \n * that the user already gave permission to\n * @returns A list of available devices\n */\nexport const getDevices = async (): Promise<UsbDevice[]> => {\n const agent = await getUSB()\n const devices = await agent.getDevices()\n return devices.map(device => new UsbDevice(device) )\n}\n\n/**\n * In node, it returns the first available device, in the browser (supported browsers only) it shows \n * a UI for the user to choose a device\n * @returns The first available device\n */\nexport const requestDevice = async (): Promise<UsbDevice|undefined> => {\n const agent = await getUSB()\n const device = await agent.requestDevice({filters: []})\n if(device) {\n return new UsbDevice(device)\n } else {\n return undefined\n }\n}\n\n /**\n * Request a USB device using WebUSB filters.\n *\n * - **Browser**: shows a device picker UI filtered by the supplied `vendorId`/`productId`.\n * - **Node.js**: uses the underlying WebUSB implementation provided by the `usb` package.\n *\n * Note: WebUSB filters support `vendorId` and `productId`. Serial filtering is not\n * part of the WebUSB request filters.\n */\n export const requestDeviceWithFilters = async (filters: UsbRequestFilter[] = []): Promise<UsbDevice|undefined> => {\n const agent = await getUSB()\n const device = await agent.requestDevice({ filters: filters as any })\n if(device) {\n return new UsbDevice(device)\n } else {\n return undefined\n }\n }\n\n/**\n * Convenience wrapper for a web usb device\n * Its main purpose is to hide the details of the usb library from client code so in case\n * it needs to be switched, compatibility can be retained\n */\nexport class UsbDevice {\n private readonly device: USBDevice\n\n get opened() {\n return this.device.opened\n }\n\n get vendorId(): number {\n return this.device.vendorId\n }\n\n get productId(): number {\n return this.device.productId\n }\n\n get serialNumber(): string|undefined {\n return this.device.serialNumber\n }\n\n /**\n * All available endpoints\n */\n private get endpoints() {\n return this.device.configuration?.interfaces[0].alternate.endpoints ?? []\n }\n\n /**\n * Endpoint for writing\n */\n private get outEndpoint() {\n return this.endpoints.find(e => e.direction == \"out\")?.endpointNumber\n }\n\n private get outEndpointPacketSize(): number|undefined {\n return this.endpoints.find(e => e.direction == \"out\")?.packetSize\n }\n\n /**\n * Endpoint for reading\n */\n private get inEndpoint() {\n return this.endpoints.find(e => e.direction == \"in\")?.endpointNumber\n }\n\n constructor(device: USBDevice) {\n this.device = device\n }\n\n /**\n * Open the device and claim its interface\n */\n async openAndConfigure() {\n await this.device.open();\n await this.device.selectConfiguration(1);\n await this.device.claimInterface(0);\n }\n\n /**\n * Closes the device\n */\n async close() {\n await this.device.releaseInterface(0)\n await this.device.close()\n }\n\n /**\n * Write data to an USB device\n * @param data Data to write\n */\n async writeData(data: Uint8Array|ArrayBuffer): Promise<void> {\n const endpointNumber = this.outEndpoint\n if(endpointNumber == null) {\n throw new Error(\"usb-no-out-endpoint\")\n }\n await this.device.transferOut(endpointNumber, data as BufferSource)\n }\n\n /**\n * Writes a text to a device\n * @param text Text to write\n */\n async writeString(text: string): Promise<void> {\n const bytes = stringHelper.toUTF8Array(text)\n await this.writeData(bytes)\n }\n\n /**\n * Reads bytes from the usb device\n * @param length The max length of the incoming data. \n * @returns Bytes received as a DataView or undefined. If data is longer then `length`, undefined will be returned\n */\n async readData(length: number): Promise<DataView|undefined> {\n const endpointNumber = this.inEndpoint\n if(endpointNumber == null) {\n throw new Error(\"usb-no-in-endpoint\")\n }\n const result = await this.device.transferIn(endpointNumber, length)\n\n if(result.status == \"ok\" && result.data) {\n return result.data\n } else {\n return undefined\n }\n }\n\n /**\n * Reads data from the usb device and converts it to string\n * {@see readData}\n */\n async readString(length: number): Promise<string|undefined> {\n const bytes = await this.readData(length)\n if(bytes) return stringHelper.toString(bytes)\n return undefined\n }\n}\n","import StringUtils from \"./StringUtils\";\nimport type Device from \"./Device\";\n\nconst unsupportedNetworkError = \"network-unsupported\"\nconst stringHelper = new StringUtils()\n\ntype NetSocket = {\n write(data: Uint8Array|ArrayBuffer|string, cb?: (err?: Error) => void): boolean\n end(): void\n destroy(): void\n on(event: \"data\", listener: (data: Buffer) => void): any\n on(event: \"error\", listener: (err: Error) => void): any\n once(event: \"data\", listener: (data: Buffer) => void): any\n once(event: \"error\", listener: (err: Error) => void): any\n removeListener(event: \"data\"|\"error\", listener: (...args: any[]) => void): any\n}\n\ntype NetModule = {\n createConnection(options: { host: string, port: number }, listener?: () => void): NetSocket\n}\n\nconst getNet = (): NetModule => {\n if(typeof window !== \"undefined\") {\n throw unsupportedNetworkError\n }\n\n // TODO: Check how to avoid eval\n return eval(\"require\")(\"net\") as NetModule\n}\n\nexport default class NetworkDevice implements Device {\n private socket?: NetSocket\n private readonly host: string\n private readonly port: number\n private readonly connectTimeoutMs: number\n private readonly readTimeoutMs: number\n\n /**\n * Create a TCP-based device.\n *\n * This is intended for raw printing ports (typically 9100). It is Node-only.\n *\n * @param host Hostname or IP\n * @param port TCP port (defaults to 9100)\n * @param connectTimeoutMs Connection timeout\n * @param readTimeoutMs Read timeout used by `readData`/`readString`\n */\n constructor(host: string, port: number = 9100, connectTimeoutMs: number = 2000, readTimeoutMs: number = 500) {\n this.host = host\n this.port = port\n this.connectTimeoutMs = connectTimeoutMs\n this.readTimeoutMs = readTimeoutMs\n }\n\n get opened(): boolean {\n return !!this.socket\n }\n\n async openAndConfigure(): Promise<void> {\n if(this.socket) return\n\n const net = getNet()\n\n await new Promise<void>((resolve, reject) => {\n let settled = false\n const timeout = setTimeout(() => {\n if(settled) return\n settled = true\n try { this.socket?.destroy() } catch (_e) {}\n this.socket = undefined\n reject(new Error(\"network-connect-timeout\"))\n }, this.connectTimeoutMs)\n\n try {\n const socket = net.createConnection({ host: this.host, port: this.port }, () => {\n if(settled) return\n settled = true\n clearTimeout(timeout)\n resolve()\n })\n\n socket.once(\"error\", (err) => {\n if(settled) return\n settled = true\n clearTimeout(timeout)\n this.socket = undefined\n reject(err)\n })\n\n this.socket = socket\n } catch (e) {\n if(settled) return\n settled = true\n clearTimeout(timeout)\n this.socket = undefined\n reject(e)\n }\n })\n }\n\n async close(): Promise<void> {\n if(!this.socket) return\n const socket = this.socket\n this.socket = undefined\n\n try {\n socket.end()\n } catch (_e) {\n try { socket.destroy() } catch (_e2) {}\n }\n }\n\n async writeData(data: Uint8Array|ArrayBuffer): Promise<void> {\n if(!this.socket) {\n throw new Error(\"network-not-open\")\n }\n\n await new Promise<void>((resolve, reject) => {\n try {\n this.socket!.write(data as any, (err?: Error) => {\n if(err) reject(err)\n else resolve()\n })\n } catch (e) {\n reject(e)\n }\n })\n }\n\n async writeString(text: string): Promise<void> {\n const bytes = stringHelper.toUTF8Array(text)\n await this.writeData(bytes)\n }\n\n async readData(length: number): Promise<DataView|undefined> {\n if(!this.socket) {\n throw new Error(\"network-not-open\")\n }\n\n const socket = this.socket\n const buffer = await new Promise<Buffer|undefined>((resolve, reject) => {\n let settled = false\n\n const onData = (data: Buffer) => {\n if(settled) return\n settled = true\n cleanup()\n resolve(data)\n }\n\n const onError = (err: Error) => {\n if(settled) return\n settled = true\n cleanup()\n reject(err)\n }\n\n const cleanup = () => {\n clearTimeout(timeout)\n socket.removeListener(\"data\", onData)\n socket.removeListener(\"error\", onError)\n }\n\n const timeout = setTimeout(() => {\n if(settled) return\n settled = true\n cleanup()\n resolve(undefined)\n }, this.readTimeoutMs)\n\n socket.once(\"data\", onData)\n socket.once(\"error\", onError)\n })\n\n if(!buffer) return undefined\n if(buffer.byteLength > length) return undefined\n\n return new DataView(buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength))\n }\n\n async readString(length: number): Promise<string|undefined> {\n const bytes = await this.readData(length)\n if(bytes) return stringHelper.toString(bytes)\n return undefined\n }\n}\n","const unsupportedBonjourError = \"bonjour-unsupported\"\n\ntype BonjourBrowser = {\n stop(): void\n on(event: \"up\", listener: (service: any) => void): any\n}\n\ntype BonjourInstance = {\n find(options: { type: string }, cb?: (service: any) => void): BonjourBrowser\n destroy(): void\n}\n\nconst getBonjour = (): (() => BonjourInstance) => {\n if(typeof window !== \"undefined\") {\n throw unsupportedBonjourError\n }\n\n // TODO: Check how to avoid eval\n const mod: any = eval(\"require\")(\"bonjour\")\n const factory: any = (mod && (mod.default ?? mod))\n if(typeof factory !== \"function\") {\n throw new Error(\"bonjour-invalid-module\")\n }\n return factory as () => BonjourInstance\n}\n\nexport type BonjourService = {\n host: string\n port: number\n name?: string\n type?: string\n}\n\n/**\n * Discover services using Bonjour/mDNS.\n *\n * This is a Node-only helper. It dynamically requires the `bonjour` module so the library can\n * still be imported/bundled in browser contexts.\n *\n * @param types Bonjour service types without the leading underscore (e.g. `printer`, `ipp`)\n * @param timeoutMs Discovery window\n */\nexport const discoverBonjourServices = async (types: string[], timeoutMs: number = 1500): Promise<BonjourService[]> => {\n if(typeof window !== \"undefined\") return []\n\n const factory = getBonjour()\n const bonjour = factory()\n\n try {\n const results: BonjourService[] = []\n const seen = new Set<string>()\n\n const browsers: BonjourBrowser[] = types.map((type) => {\n return bonjour.find({ type }, (service: any) => {\n const host = service?.referer?.address || service?.host\n const port = service?.port\n if(!host || !port) return\n\n const key = `${host}:${port}`\n if(seen.has(key)) return\n seen.add(key)\n\n results.push({ host, port, name: service?.name, type })\n })\n })\n\n await new Promise<void>((resolve) => setTimeout(resolve, timeoutMs))\n\n for (const browser of browsers) {\n try { browser.stop() } catch (_e) {}\n }\n\n return results\n } finally {\n try { bonjour.destroy() } catch (_e) {}\n }\n}\n","import { TSPLRawCommand } from \"@/commands/tspl\";\nimport { PrinterLanguage } from \"@/commands\"\nimport Printer, { PrinterStatus } from \"./Printer\";\nimport Device from \"@/helpers/Device\";\nimport NetworkDevice from \"@/helpers/NetworkDevice\";\nimport { discoverBonjourServices } from \"@/helpers/BonjourUtils\";\n\nexport default class TSPLPrinter extends Printer {\n get language(): PrinterLanguage {\n return \"tspl\"\n }\n\n async feedLabel(): Promise<void> {\n const feedCommand = new TSPLRawCommand(\"FORMFEED\")\n await this.writeCommand(feedCommand)\n }\n\n async getModelname(): Promise<string> {\n if(!this.device.opened) await this.device.openAndConfigure()\n const command = new TSPLRawCommand(\"~!T\")\n await command.writeTo(this.device)\n\n const response = await this.device.readString(256)\n return (response ?? \"\").trim()\n }\n\n async getStatus(): Promise<PrinterStatus> {\n if(!this.device.opened) await this.device.openAndConfigure()\n\n await this.device.writeData(new Uint8Array([0x1b, 0x21, 0x3f, 0x0a]))\n\n const data = await this.device.readData(1)\n const raw = data ? data.getUint8(0) : 0x80\n\n return TSPLPrinter.statusFor(raw)\n }\n\n private static statusFor(code: number): PrinterStatus {\n const map: Record<number, PrinterStatus> = {\n 0x00: \"normal\",\n 0x01: \"head_opened\",\n 0x02: \"paper_jam\",\n 0x03: \"paper_jam_head_opened\",\n 0x04: \"out_of_paper\",\n 0x05: \"out_of_paper_head_opened\",\n 0x08: \"out_of_ribbon\",\n 0x09: \"out_of_ribbon_head_opened\",\n 0x0A: \"out_of_ribbon_paper_jam\",\n 0x0B: \"out_of_ribbon_paper_jam_head_opened\",\n 0x0C: \"out_of_ribbon_out_of_paper\",\n 0x0D: \"out_of_ribbon_out_of_paper_head_opened\",\n 0x10: \"paused\",\n 0x20: \"printing\",\n 0x80: \"other_error\",\n }\n\n return map[code] ?? \"other_error\"\n }\n\n static async try(device: Device): Promise<boolean> {\n if(!device.opened) await device.openAndConfigure()\n const testCommand = new TSPLRawCommand(\"~!I\")\n await testCommand.writeTo(device)\n\n const response = await device.readString(64)\n await device.close()\n // If there is a response, we have a TSPL printer\n return !!response\n }\n\n /**\n * Discover TSPL-capable printers on the local network.\n *\n * Strategy:\n * - Use Bonjour/mDNS to discover \"printer-ish\" services to obtain a set of candidate hosts.\n * - For each unique host, probe TCP/9100 by sending the TSPL identify command (~!I).\n * - Only return devices that respond to the TSPL probe.\n * - If Bonjour yields no candidates (e.g. mDNS is blocked), fall back to a conservative\n * subnet scan on local private /24 networks (still verified by the same TSPL probe).\n */\n static async discoverDevices(): Promise<NetworkDevice[]> {\n if(typeof window !== \"undefined\") return []\n\n const services = await discoverBonjourServices([\n \"pdl-datastream\",\n \"printer\",\n \"ipp\",\n \"ipps\",\n ])\n\n let uniqueHosts = Array.from(new Set(services.map(s => s.host).filter(Boolean)))\n\n if(uniqueHosts.length === 0) {\n uniqueHosts = await TSPLPrinter.discoverHostsBySubnetScan()\n }\n\n const candidates = uniqueHosts.map(host => ({ host, port: 9100 }))\n\n const concurrency = 5\n const verified: NetworkDevice[] = []\n\n for (let i = 0; i < candidates.length; i += concurrency) {\n const batch = candidates.slice(i, i + concurrency)\n\n const results = await Promise.all(batch.map(async (c) => {\n const device = new NetworkDevice(c.host, c.port, 4000, 1000)\n try {\n const ok = await TSPLPrinter.try(device)\n return ok ? device : undefined\n } catch (_e) {\n try { await device.close() } catch (_e2) {}\n return undefined\n }\n }))\n\n verified.push(...(results.filter(Boolean) as NetworkDevice[]))\n }\n\n return verified\n }\n\n /**\n * Fallback discovery mechanism used when Bonjour/mDNS returns no printer candidates.\n *\n * It derives local private IPv4 /24 prefixes from the current machine's network interfaces\n * and probes TCP/9100 using the TSPL identify command.\n *\n * The scan is intentionally conservative:\n * - Limited number of prefixes\n * - Concurrency limits\n * - Total time cap\n * - Early-exit when at least one printer is found\n */\n private static async discoverHostsBySubnetScan(): Promise<string[]> {\n if(typeof window !== \"undefined\") return []\n\n const req = TSPLPrinter.getNodeRequire()\n if(!req) return []\n\n const os: any = req(\"os\")\n const networkInterfaces: any = os.networkInterfaces?.() ?? {}\n\n const privatePrefixes = new Set<string>()\n\n const isPrivateIpv4 = (ip: string): boolean => {\n if(ip.startsWith(\"10.\")) return true\n if(ip.startsWith(\"192.168.\")) return true\n const m = ip.match(/^172\\.(\\d+)\\./)\n if(m) {\n const n = Number(m[1])\n return n >= 16 && n <= 31\n }\n return false\n }\n\n for (const key of Object.keys(networkInterfaces)) {\n const infos = networkInterfaces[key] ?? []\n for (const info of infos) {\n const family = info?.family\n const address = info?.address\n const internal = info?.internal\n if(internal) continue\n if(family !== \"IPv4\") continue\n if(typeof address !== \"string\") continue\n if(!isPrivateIpv4(address)) continue\n\n const parts = address.split(\".\")\n if(parts.length !== 4) continue\n privatePrefixes.add(`${parts[0]}.${parts[1]}.${parts[2]}`)\n }\n }\n\n const prefixes = Array.from(privatePrefixes).slice(0, 2)\n if(prefixes.length === 0) return []\n\n const hosts: string[] = []\n for (const prefix of prefixes) {\n for (let i = 1; i <= 254; i++) {\n hosts.push(`${prefix}.${i}`)\n }\n }\n\n const concurrency = 30\n const verifiedHosts: string[] = []\n const startedAt = Date.now()\n const maxDurationMs = 15000\n\n for (let i = 0; i < hosts.length; i += concurrency) {\n if(Date.now() - startedAt > maxDurationMs) break\n if(verifiedHosts.length > 0) break\n const batch = hosts.slice(i, i + concurrency)\n const results = await Promise.all(batch.map(async (host) => {\n const device = new NetworkDevice(host, 9100, 800, 800)\n try {\n const ok = await TSPLPrinter.try(device)\n return ok ? host : undefined\n } catch (_e) {\n try { await device.close() } catch (_e2) {}\n return undefined\n }\n }))\n\n verifiedHosts.push(...(results.filter(Boolean) as string[]))\n }\n\n return verifiedHosts\n }\n\n /**\n * Returns a Node-style `require` function.\n *\n * This is used to keep runtime dependencies Node-only while still allowing the library to\n * be imported/bundled in browser contexts.\n *\n * Tests may inject a custom require implementation via `globalThis.__label_printer_require`.\n */\n private static getNodeRequire(): ((module: string) => any) | undefined {\n if(typeof window !== \"undefined\") return undefined\n\n const override = (globalThis as any).__label_printer_require\n if(typeof override === \"function\") return override\n\n // TODO: Check how to avoid eval\n return eval(\"require\")\n }\n}","import Device from \"@/helpers/Device\"\nimport { getDevices, requestDevice, requestDeviceWithFilters } from \"@/helpers/USBUtils\"\nimport NetworkDevice from \"@/helpers/NetworkDevice\"\nimport TSPLPrinter from \"./TSPLPrinter\"\nimport Printer from \"./Printer\"\n\nexport type PrinterServiceUsbConnectOptions = {\n vendorId?: number\n productId?: number\n serialNumber?: string\n}\n\nexport type PrinterServiceNetworkConnectOptions = {\n host: string\n port?: number\n}\n\nexport type PrinterServiceConnectOptions =\n | { usb: PrinterServiceUsbConnectOptions }\n | { network: PrinterServiceNetworkConnectOptions }\n\nexport class PrinterService {\n /**\n * Try each type of printer and return the one that mathces the usb device\n * @param device \n * @returns \n */\n static async printerForDevice(device: Device): Promise<Printer|undefined> {\n const classes = [TSPLPrinter]\n\n for (const key in classes) {\n try {\n if(await classes[key].try(device)) {\n return new classes[key](device)\n }\n } catch (_e) {\n return undefined\n }\n }\n\n return undefined\n }\n\n /**\n * Discover devices using printer-specific discovery hooks.\n *\n * Each printer class may optionally implement `static discoverDevices(): Promise<Device[]>`\n * to find candidates over non-USB transports.\n *\n * Candidates returned here are still verified by `printerForDevice` via the printer\n * class' `try(device)` method.\n */\n private static async discoverDevices(): Promise<Device[]> {\n const classes = [TSPLPrinter]\n\n const discoveryResults = await Promise.all(classes.map(async (cls) => {\n const discoverer = (cls as any).discoverDevices\n if(typeof discoverer === \"function\") {\n try {\n return await discoverer.call(cls)\n } catch (_e) {\n return []\n }\n }\n return []\n }))\n\n return discoveryResults.flat()\n }\n\n /**\n * @returns List of available printers\n */\n static async getPrinters(): Promise<Printer[]> {\n const usbDevices = await getDevices()\n const discoveredDevices = await PrinterService.discoverDevices()\n const devices: Device[] = [...usbDevices, ...discoveredDevices]\n\n const optionalPrinters = await Promise.all(devices.map(PrinterService.printerForDevice))\n return optionalPrinters.filter(printer => !!printer) as Printer[]\n }\n\n /**\n * This is intended to be used in the browser although it also works in node\n * In the browser, it provides a UI for the user to choose a USB device and if it is a\n * printer, it returns a new printer instance. In Node however, this will try to create\n * a printer for the first available device and returns it. This means that even if there is a \n * printer, it may return undefined. In node, use `getPrinters` instead\n */\n static async requestPrinter(): Promise<Printer|undefined> {\n const device = await requestDevice()\n if(device) {\n return PrinterService.printerForDevice(device)\n }\n }\n\n /**\n * Create a printer instance using explicit connection information.\n *\n * This is useful when you already know your printer's network address or USB identifiers\n * and want to bypass discovery.\n *\n * Behavior differs by environment:\n * - **Node.js**\n * - `network`: connects via TCP (defaults to port `9100`)\n * - `usb`: selects the first connected USB device matching the provided filters\n * - **Browser**\n * - `usb`: shows the WebUSB picker (optionally filtered by `vendorId`/`productId`)\n * - `network`: not supported (will throw if network transport is used in the browser)\n */\n static async connect(options: PrinterServiceConnectOptions): Promise<Printer|undefined> {\n const device = await PrinterService.deviceForConnectOptions(options)\n if(!device) return undefined\n return PrinterService.printerForDevice(device)\n }\n\n /**\n * Create a TSPL printer instance using explicit connection information.\n *\n * This still verifies the target by probing it with the TSPL identify command (`~!I`).\n * If the probe fails, `undefined` is returned.\n */\n static async connectTSPL(options: PrinterServiceConnectOptions): Promise<TSPLPrinter|undefined> {\n const device = await PrinterService.deviceForConnectOptions(options)\n if(!device) return undefined\n\n const ok = await TSPLPrinter.try(device)\n if(!ok) return undefined\n return new TSPLPrinter(device)\n }\n\n /**\n * Convert user-facing connect options into a concrete device.\n *\n * This keeps transport details (USB vs TCP socket) out of the public API.\n */\n private static async deviceForConnectOptions(options: PrinterServiceConnectOptions): Promise<Device|undefined> {\n if(\"network\" in options) {\n const port = options.network.port ?? 9100\n return new NetworkDevice(options.network.host, port)\n }\n\n const filters = [{ vendorId: options.usb.vendorId, productId: options.usb.productId }].filter(f => f.vendorId != null || f.productId != null)\n\n if(typeof window !== \"undefined\") {\n if(filters.length > 0) return requestDeviceWithFilters(filters as any)\n return requestDevice()\n }\n\n const devices = await getDevices()\n\n const matching = devices.filter(d => {\n if(options.usb.vendorId != null && d.vendorId !== options.usb.vendorId) return false\n if(options.usb.productId != null && d.productId !== options.usb.productId) return false\n if(options.usb.serialNumber != null && d.serialNumber !== options.usb.serialNumber) return false\n return true\n })\n\n return matching[0]\n }\n}","export { default as Label } from \"./Label\"\nexport * from \"./fields\"","import { Command, PrinterLanguage, tspl } from \"@/commands\";\nimport CommandGenerator from \"@/commands/CommandGenerator\";\nimport { Printer } from \"@/printers\";\nimport { FontOption } from \"./types\";\n\nexport type PrintConfig = {\n dpi: number,\n /** Width of the text in dots */\n textWidth: (text: string, font: FontOption) => number,\n getFontName: (font: FontOption) => string\n}\n\n/**\n * A component that can be directly printed to label printer\n */\nexport default abstract class Printable {\n /**\n * Generates a printable command\n * @param language The printing language that should be used\n * @returns A promise of a command that can be printed\n */\n abstract commandForLanguage(language: PrinterLanguage, config?: PrintConfig): Promise<Command>\n\n /**\n * Generates printable command for the given printer. Can be used to obtain a command for fields supported by the package then customizing it before printing\n * @param printer Printer to generate the command. Important because the command is printer language specific\n * @returns A promise for a command. Most commands are syncronouse but some may require to access async resources\n */\n async commandForPrinter(printer: Printer, config?: PrintConfig): Promise<Command> {\n return await this.commandForLanguage(printer.language, config)\n }\n\n /**\n * Obtain a command generator for the given language\n * @param language Language to get generator for\n */\n protected commandGeneratorFor(language: PrinterLanguage): CommandGenerator<any> {\n switch(language) {\n case \"tspl\": return tspl.commandGenerator\n }\n }\n}","import { Command, PrinterLanguage } from \"@/commands\";\nimport Printable, { PrintConfig } from \"./Printable\";\nimport { UnitSystem } from \"@/commands\";\nimport { LabelDirection } from \"@/commands/tspl\";\nimport LabelField from \"./fields/LabelField\";\nimport { Font, FontOption, FontStyle, IndexedFont, IndexedFontFamily } from \"./types\";\nimport CommandGenerator from \"@/commands/CommandGenerator\";\nimport * as fontkit from \"fontkit\"\nimport { dotToPoint, pointsToDots } from \"@/helpers/UnitUtils\";\n\nconst DEFAULT_FONT_WEIGHT = 400\nconst DEFAULT_FONT_STYLE = \"normal\"\nconst FONT_PREFIX = \"f\"\n\n/**\n * Holds the content of a label and handles printing\n */\nexport default class Label extends Printable {\n /**\n * Width of label in dots, mm or inch\n */\n private readonly width: number\n /**\n * Height of label in dots, mm or inch\n */\n private readonly height: number\n\n /**\n * Units for width, height, gap and offset\n */\n private readonly unitSystem: UnitSystem\n private fonts: Record<string, IndexedFontFamily> = {}\n private dpi: number\n\n /**\n * List of fields on the label\n */\n private fields: LabelField[] = []\n private fontCounter = 0\n\n /**\n * Configuration used when generating commands\n */\n get printConfig(): PrintConfig {\n return { \n dpi: this.dpi,\n textWidth: (text, font) => {\n const indexedFont = this.getIndexedFont(font)\n if(indexedFont == null) {\n return text.length * font.size\n } else {\n const size = dotToPoint(font.size, this.dpi)\n const fontObject = indexedFont.font\n \n const run = fontObject.layout(text)\n\n const scaledWidth = size * run.advanceWidth / fontObject.unitsPerEm\n return pointsToDots(scaledWidth, this.dpi)\n }\n },\n getFontName: this.getFontName.bind(this)\n } \n }\n\n constructor(width: number, height: number, dimensionUnit: UnitSystem = \"metric\", dpi: number = 203) {\n super()\n this.width = width\n this.height = height\n this.unitSystem = dimensionUnit\n this.dpi = dpi\n }\n\n async commandForLanguage(language: PrinterLanguage, config?: PrintConfig): Promise<Command> {\n const configuration = config ?? this.printConfig\n const commandList = await Promise.all(this.fields.map(field => field.commandForLanguage(language, configuration)))\n return this.commandGeneratorFor(language).commandGroup(commandList)\n }\n\n /**\n * Place fields to a label\n * @param fields \n */\n add(...fields: LabelField[]) {\n this.fields.push(...fields)\n }\n\n /**\n * Register a font to be used. Use the name provided in components to use the font. \n * For example: textField.setFont('myFont.ttf', 12)\n * @param file Font file. Can be a blob or a url\n * @param name Name to be used to reference the font\n */\n async registerFont(font: Omit<Font, \"font\">) {\n const key = this.fontKey(font.weight, font.style)\n\n if(!this.fonts[font.name]) {\n this.fonts[font.name] = {\n fonts: {}\n }\n }\n\n const fontBuffer = Buffer.from(font.data)\n const builtFont = fontkit.create(fontBuffer)\n // @ts-ignore\n const finalFont = builtFont.fonts ? builtFont.fonts[0] : builtFont\n this.fonts[font.name].fonts[key] = {\n ...font,\n font: finalFont,\n alias: `${FONT_PREFIX}${this.fontCounter}.${this.fontExtension}`\n }\n this.fontCounter += 1\n }\n\n /**\n * Generate a command that is complete for printing\n * @param language Printing language to use\n * @param gap Distance between two labels. It is measured between the two points where the sensor \n * leaves the label and enters the next one\n * @param direction Direction relative to printing direction. See documentation for more details\n * @param sets Number of sets to print. If you have counters for example, it will not change in a set\n * @param copiesPerSet Number of labels per set\n * @param mirror Mirror the label along the vertical axis\n * @param gapOffset Used with non uniform shaped labels. Is the distance between the point where the sensor leaves the label and the \n * furthest point of the label in the direction of printing. Check documentation for more info\n * TODO: Is this too TSPL Specific?\n */\n async fullPrintCommand(language: PrinterLanguage, \n gap: number, \n direction: LabelDirection, \n sets: number, \n copiesPerSet: number = 1,\n mirror: boolean = false, \n gapOffset: number = 0\n ): Promise<Command> {\n\n const generator = this.commandGeneratorFor(language)\n const commands = await this.fullCommand(language, gap, direction, mirror, gapOffset, generator)\n commands.push(generator.print(sets, copiesPerSet))\n\n return generator.commandGroup(commands)\n }\n\n /**\n * Generate commands needed to display the label on the printer screen\n * @param language Printing language to use\n * @param direction Direction relative to printing direction. See documentation for more details\n * @param mirror Mirror the label along the vertical axis\n */\n async fullDisplayCommand(language: PrinterLanguage, direction: LabelDirection, mirror: boolean = false) {\n const generator = this.commandGeneratorFor(language)\n const commands = await this.fullCommand(language, 0, direction, mirror, 0, generator)\n commands.push(generator.display())\n \n return generator.commandGroup(commands)\n }\n\n /**\n * Helper function that generates common commands for print and display\n */\n private async fullCommand(language: PrinterLanguage, \n gap: number, \n direction: LabelDirection, \n mirror: boolean = false, \n gapOffset: number = 0, \n generator: CommandGenerator<any>) {\n const commands = [\n this.fontUploadCommands(generator),\n generator.setUp(this.width, this.height, gap, gapOffset, direction, mirror, this.unitSystem),\n (await this.commandForLanguage(language, this.printConfig)),\n ]\n return commands\n }\n\n private fontUploadCommands(generator: CommandGenerator<any>): Command {\n const families = Object.keys(this.fonts)\n const commands = families.flatMap(family => {\n const familyFonts = this.fonts[family].fonts\n const fontNames = Object.keys(familyFonts)\n\n return fontNames.map(name => {\n const font = familyFonts[name]\n const fileName = font.alias\n\n // @ts-ignore\n return generator.upload(fileName, font.data)\n })\n })\n\n return generator.commandGroup(commands)\n }\n\n private getIndexedFont(font: FontOption): IndexedFont|null {\n const family = this.fonts[font.name]\n if (!family) return null\n \n const style = font.style ?? DEFAULT_FONT_STYLE\n const weigth = font.weight ?? DEFAULT_FONT_WEIGHT\n\n const fontKeys = Object.keys(family.fonts)\n const exactMatch = fontKeys.find(key => \n family.fonts[key].style == style &&\n family.fonts[key].weight == weigth\n )\n\n // If there is a font that matches exactly the requested one we return that\n // otherwise we find the one that is the closest in weight\n // if there is no font with the same style, we return the first normal font in the family\n if(exactMatch) {\n return family.fonts[exactMatch]\n } else {\n const sameStyleKeys = fontKeys.filter(key => family.fonts[key].style == style)\n\n if(sameStyleKeys.length > 0){\n let weigthDiff = 99999999\n let selectedKey = \"\"\n\n sameStyleKeys.forEach(key => {\n const diff = Math.abs(weigth - family.fonts[key].weight)\n if(diff < weigthDiff) {\n weigthDiff = diff\n selectedKey = key\n }\n })\n\n return family.fonts[selectedKey]\n } else {\n return family.fonts[fontKeys[0]]\n }\n }\n }\n\n private getFontName(font: FontOption) {\n // We don't access values directly passed in to make sure the font name we return exists\n const indexedFont = this.getIndexedFont(font)\n if(indexedFont == null) {\n return font.name\n }\n return indexedFont.alias\n // return this.getFontNameForIndexed({name: font.name, weight: indexedFont.weight, style: indexedFont.style})\n }\n\n /// This can be extended when we want support multiple fonts\n private get fontExtension() {\n return \"TTF\"\n }\n\n private fontKey(weight: number, style?: FontStyle) {\n return `${weight}${style ?? DEFAULT_FONT_STYLE}`\n }\n}","import Printable from \"../Printable\";\n\nexport default abstract class LabelField extends Printable {}","import { Command, Point, PrinterLanguage } from \"@/commands\";\nimport LabelField from \"./LabelField\";\n\n/**\n * Draws a line to the screen\n */\nexport default class Line extends LabelField {\n private readonly start: Point\n private readonly end: Point\n private readonly thickness: number\n\n /**\n * \n * @param start Start point of the line. Values are in dots\n * @param end End point of the line. Values are in dots\n * @param thickness Thickness of the line in dots \n */\n constructor(start: Point, end: Point, thickness: number = 3) {\n super()\n this.start = start\n this.end = end\n this.thickness = thickness\n }\n\n commandForLanguage(language: PrinterLanguage): Promise<Command> {\n return this.commandGeneratorFor(language).line(this.start, this.end, this.thickness)\n }\n}","import { Command, PrinterLanguage } from \"@/commands\"\nimport LabelField from \"./LabelField\"\nimport { PrintConfig } from \"../Printable\"\nimport { dotToPoint } from \"@/helpers/UnitUtils\"\nimport CommandGenerator from \"@/commands/CommandGenerator\"\nimport { isWhitespace } from \"@/helpers/StringUtils\"\nimport { NodeType, parse, HTMLElement, Node } from \"node-html-parser\"\nimport { FontOption } from \"../types\"\n\nexport type TextFieldType = \"singleline\"|\"multiline\"\ntype Context = {\n language: PrinterLanguage,\n generator: CommandGenerator<any>,\n config?: PrintConfig\n}\n\ntype TextDecoration = \"underline\"|\"strike\"\n\nconst BOLD_WEIGTH = 700\nconst BOLD_TAG = \"b\"\nconst ITALIC_TAG = \"i\"\nconst UNDERLINE_TAG = \"u\"\nconst STRIKE_TAG = [\"s\", \"del\", \"strike\"]\nconst PARAGRAPH_TAG = \"p\"\nconst BREAK_TAG = \"br\"\n\n/**\n * Presents a piece of text on the label\n */\nexport default class Text extends LabelField {\n private readonly content: string\n /**\n * X coordinate in dots\n */\n private readonly x: number\n /**\n * Y coordinate in dots\n */\n private readonly y: number\n /**\n * If true, basic html elements will be interpretted, otherwise the raw string is printed out\n */\n private readonly formatted: boolean\n private font: FontOption = {name: \"default\", size: 10}\n private type: TextFieldType = \"singleline\"\n private context: Context|undefined = undefined\n private readonly lineSpacing = 1\n\n /**\n * Width of the text. \n * If set, the text will be clipped to this size\n * If the type is set to multiline, this is where the text is split to a newline\n */\n private width: number|undefined\n /**\n * Height of the text box, if empty and the type is multiline, the box can grow infinitely\n */\n private height: number|undefined\n \n constructor(content: string, x: number, y: number, formatted: boolean = true) {\n super()\n this.content = content.replace(\"\\n\", \"\").replace(\"\\\"\", \"\\\\\\\"\") // Newline can break text generation\n this.x = x\n this.y = y\n this.formatted = formatted\n }\n\n /**\n * Sets the field to single line\n * @param width Max width of the text. Leave it undefined to allow the field to grow \n */\n setSingleLine(width?: number) {\n this.type = \"singleline\"\n this.width = width\n this.height = undefined\n }\n\n /**\n * Sets the field to multi line\n * @param width Max width of text before it gets wrapped to a new line\n * @param height Max height of the text box, leave undefined to allow the text box to grow infinitly\n */\n setMultiLine(width: number, height?: number) {\n this.type = \"multiline\"\n this.width = width\n this.height = height\n }\n\n /**\n * Set a font to use as a base. If no formatting is set on the text with a html tag, this will be used \n * Note: The font name either has to be a built in font on your printer or a font\n * that is registered on the label using 'registerFont'.\n */\n setFont(font: FontOption) {\n this.font = font\n }\n\n async commandForLanguage(language: PrinterLanguage, config?: PrintConfig): Promise<Command> {\n this.context = {\n config,\n language,\n generator: this.commandGeneratorFor(language)\n }\n\n let command: Command\n if(this.formatted) {\n command = this.generateFormattedText()\n } else {\n command = this.generatePlainText()\n }\n this.context = undefined\n \n return command\n }\n \n /**\n * Generate commands for formatted text\n * @returns \n */\n private generateFormattedText(): Command {\n if(!this.context) throw \"context-not-set\"\n \n const rootNode = parse(this.content)\n const { command } = this.generateFormattedRecursive(this.x, this.y, rootNode, this.font, [])\n return command\n }\n\n /**\n * Generate commands for plain text\n * @returns \n */\n private generatePlainText(): Command {\n const { command } = this.generatePlainTextCore(this.content, this.x, this.y, this.font)\n return command\n }\n\n /**\n * Iterats the nodes in a html text and generates text commands for it\n */\n private generateFormattedRecursive(initialX: number, initialY: number, rootNode: Node, font: FontOption, features: TextDecoration[]): {x: number, y: number, command: Command} {\n if(rootNode.nodeType == NodeType.TEXT_NODE) {\n const result = this.generatePlainTextCore(rootNode.innerText, initialX, initialY, font, features)\n return result\n } else {\n const elementNode = rootNode as HTMLElement\n const tag = elementNode.rawTagName\n\n if(tag == BREAK_TAG) {\n return {\n x: this.x,\n y: initialY + font.size + this.lineSpacing,\n command: this.context!.generator.commandGroup([])\n }\n }\n\n let commands: Command[] = []\n let currentX = initialX\n let currentY = initialY\n\n let baseFont = {...font}\n let baseFeatures = [...features]\n \n if(tag == UNDERLINE_TAG) {\n baseFeatures.push(\"underline\")\n } else if(STRIKE_TAG.includes(tag)) {\n baseFeatures.push(\"strike\")\n } else if(tag == BOLD_TAG) {\n baseFont.weight = BOLD_WEIGTH\n } else if(tag == ITALIC_TAG) {\n baseFont.style = \"italic\"\n }\n\n // Treat paragraphs as block-level elements: start and end on a new line.\n // Avoid adding an extra leading newline if the paragraph starts at the field origin.\n if(tag == PARAGRAPH_TAG) {\n const isAtFieldOrigin = initialX == this.x && initialY == this.y\n if(!isAtFieldOrigin) {\n currentX = this.x\n currentY = initialY + baseFont.size + this.lineSpacing\n }\n }\n\n elementNode.childNodes.forEach(node => {\n const {x,y,command} = this.generateFormattedRecursive(currentX, currentY, node, baseFont, baseFeatures)\n currentX = x\n currentY = y\n commands.push(command)\n })\n\n if(tag == PARAGRAPH_TAG) {\n let paragraphEndsWithBreak = false\n for(let i = elementNode.childNodes.length - 1; i >= 0; i--) {\n const node = elementNode.childNodes[i]\n if(node.nodeType == NodeType.TEXT_NODE) {\n if(node.innerText.trim() == \"\") continue\n break\n }\n\n const childElement = node as HTMLElement\n if(childElement.rawTagName == BREAK_TAG) {\n paragraphEndsWithBreak = true\n }\n break\n }\n\n if(!paragraphEndsWithBreak) {\n currentX = this.x\n currentY += baseFont.size + this.lineSpacing\n }\n }\n\n return {\n x: currentX,\n y: currentY,\n command: this.context!.generator.commandGroup(commands)\n }\n }\n }\n\n /**\n * Generate commands for plain text\n * @param config \n * @returns \n */\n private generatePlainTextCore(content: string, initialX: number, initialY: number, font: FontOption, features: TextDecoration[] = []): {x: number, y: number, command: Command} {\n if(!this.context) throw \"context-not-set\"\n\n const textWidhtFunction = this.textWidthFunction\n let fullWidth = textWidhtFunction(content, font)\n\n if(this.width) {\n const initialPadding = initialX - this.x\n // Because we may start from further in the row, the first rows width may be smaller\n let rowWidth = this.width - initialPadding\n // In theory rowWidth should not be negative, but for some reson it happens.. as a quick work around we make sure it is not negative\n if(rowWidth <= 0) {\n rowWidth = this.width\n initialX = this.x\n initialY += font.size + this.lineSpacing\n }\n\n // Make sure we don't print spaces at the beginig of a row\n if(initialX == this.x) {\n content = content.trimStart()\n fullWidth = textWidhtFunction(content, font)\n }\n\n // We may not start from the begining of the textbox so we have to offset\n // by our current position\n if(fullWidth <= rowWidth) {\n return {\n x: initialX + fullWidth,\n y: initialY,\n command: this.textCommand(content, initialX, initialY, font, features)\n }\n } else {\n const commands: Command[] = []\n \n let x = initialX\n let y = initialY\n let remainingContent = content\n let remainingWidth = fullWidth\n let currentHeight = 0\n\n let finalX = x\n let finalY = y\n\n do {\n // This will be the last row of the text. \n if(remainingWidth < rowWidth) {\n finalX = x + remainingWidth\n finalY = y\n\n commands.push(this.textCommand(remainingContent, x, y, font, features))\n remainingContent = \"\"\n } else {\n // On how many rows this text would fit\n let rows = remainingWidth / rowWidth\n\n // From the second row, all rows are full width\n rowWidth = this.width\n // Which caracter is the last if dividing into the right number of rows\n let rowEndIndex = Math.floor(remainingContent.length / rows)\n let originalRowEndIndex = rowEndIndex\n\n // This means we have to fit a relatively short text into\n // a lot of rows which can only happen if the row width is very small\n // in this case, we have to go to a new line\n // This is used to avoid having to calculate the width of the first character of the current text, to compare with the remainig length\n if(rowEndIndex == 0) {\n x = this.x\n y += font.size + this.lineSpacing\n continue\n }\n\n // Scenario 1: Current index is in a middle of row\n // I am iron m@n\n // End this row with the last words last character\n\n // Scneraio 2: Current index is space:\n // I am iron@man\n // No action, but to simplify code, we threat as scenario 1\n\n // Scenario 3: Current index is right before a sapce\n // I am iro@ man\n // Start next row from the first latter\n\n // Find the end of the last word\n while(\n ! (\n !isWhitespace(remainingContent.charAt(rowEndIndex)) &&\n (\n rowEndIndex == remainingContent.length - 1 ||\n isWhitespace(remainingContent.charAt(rowEndIndex + 1))\n )\n ) && rowEndIndex > 0\n ) { rowEndIndex -- }\n\n let nextRowStartIndex = rowEndIndex + 1\n // We didn't find a space, we split the text wherever we land\n if(rowEndIndex == 0) {\n rowEndIndex = originalRowEndIndex\n nextRowStartIndex = originalRowEndIndex + 1\n } else {\n while(\n isWhitespace(remainingContent.charAt(nextRowStartIndex)) && \n nextRowStartIndex < remainingContent.length\n ) { nextRowStartIndex ++ }\n }\n\n const thisRow = remainingContent.substring(0, rowEndIndex + 1)\n commands.push(this.textCommand(thisRow, x, y, font, features))\n\n if(nextRowStartIndex == remainingContent.length) {\n finalX = x + remainingWidth\n finalY = y\n }\n\n // Make sure to move the cursor back to the left side of the text box\n // as we may have started further into the row\n x = this.x\n y += font.size + this.lineSpacing\n currentHeight = y - this.y\n\n remainingContent = remainingContent.substring(nextRowStartIndex)\n remainingWidth = textWidhtFunction(remainingContent, font)\n }\n } while(\n // We don't have a height constraint or we are still within bounds \n // and there is still content \n // and we are supporting multiline\n (this.height == undefined || (currentHeight + font.size) <= this.height) &&\n (remainingContent != \"\") &&\n this.type == \"multiline\"\n )\n return {\n x: finalX,\n y: finalY,\n command: this.context!.generator.commandGroup(commands)\n }\n }\n } else {\n return {\n x: initialX + fullWidth,\n y: initialY,\n command: this.textCommand(content, initialX, initialY, font, features)\n }\n }\n }\n\n private textCommand(text: string, x: number, y: number, font: FontOption, features: TextDecoration[]) {\n if(!this.context) throw \"no-context\"\n const finalFontSize = dotToPoint(font.size, this.context!.config?.dpi ?? 203)\n const finalFont = this.getFontName(font)\n const finalX = Math.round(x)\n const finalY = Math.round(y)\n\n let commands: Command[] = []\n const textCommand = this.context!.generator.text(text, finalX, finalY, finalFont, finalFontSize)\n\n if(features.length == 0) {\n return textCommand\n } else {\n let lineHeight = font.size * 0.1\n let textWidth = this.textWidthFunction(text, font)\n\n if(features.includes(\"strike\")) {\n commands.push(this.textLineCommand(textWidth, x, y, lineHeight, 0.5, font.size))\n }\n\n if(features.includes(\"underline\")) {\n commands.push(this.textLineCommand(textWidth, x, y, lineHeight, 0.9, font.size))\n }\n\n commands.push(textCommand)\n }\n\n return this.context.generator.commandGroup(commands)\n }\n\n private textLineCommand(width: number, x: number, y: number, lineHeight: number, linePercentage: number, fontSize: number): Command {\n const sy = Math.round(y + (fontSize * linePercentage) - (lineHeight / 2))\n\n const sx = Math.round(x)\n return this.context!.generator.line(\n {x: sx, y: sy}, \n {x: sx + width, y: sy}, \n lineHeight)\n }\n\n private getFontName(font: FontOption) {\n if(!this.context) throw \"no-context\"\n if(font.name == \"default\") {\n return \"default\"\n } else {\n return this.context!.config?.getFontName(font)!\n }\n }\n\n private get textWidthFunction() {\n if(this.font.name == \"default\") {\n return this.defaultTextWidth\n } else {\n return this.context?.config?.textWidth ?? this.defaultTextWidth\n }\n }\n\n /**\n * This function is used to calculate the font size if no\n * print config is provided. This will asume that the font has square characters\n */\n private defaultTextWidth(text: string, font: FontOption) {\n return text.length * font.size\n }\n}","import { Command, PrinterLanguage } from \"@/commands\";\nimport { PrintConfig } from \"../Printable\";\nimport LabelField from \"./LabelField\"\nimport { Alignment, BarcodeHumanReable, BarcodeType, Rotation } from \"@/commands/tspl\";\n\nexport default class BarCode extends LabelField {\n private readonly content: string\n private readonly x: number\n private readonly y: number\n private readonly type: BarcodeType\n private readonly height: number\n private rotation: Rotation\n private humanReadable: BarcodeHumanReable \n private readonly alignment: Alignment\n\n constructor(content: string, x: number, y: number, type: BarcodeType, height: number) {\n super()\n this.content = content\n this.x = x\n this.y = y\n this.type = type\n this.height = height\n this.rotation = 0\n this.humanReadable = \"none\"\n this.alignment = \"left\"\n }\n\n setRotation(rotation: Rotation) {\n this.rotation = rotation\n }\n\n setHumanReadable(humanReadable: BarcodeHumanReable) {\n this.humanReadable = humanReadable\n }\n\n async commandForLanguage(language: PrinterLanguage, _config?: PrintConfig | undefined): Promise<Command> {\n return await this.commandGeneratorFor(language).barCode(this.content, this.x, this.y, this.type, this.height, this.rotation, this.humanReadable, this.alignment)\n }\n}","import { Command, PrinterLanguage } from \"@/commands\";\nimport { PrintConfig } from \"../Printable\";\nimport LabelField from \"./LabelField\";\nimport ImageUtils, { BitmapLike } from \"@/helpers/ImageUtils\";\n\nexport default class Image extends LabelField {\n /**\n * X coordinate in dots\n */\n private readonly x: number\n /**\n * Y coordinate in dots\n */\n private readonly y: number\n\n private readonly image: BitmapLike\n\n constructor(x: number, y: number, image: BitmapLike) {\n super()\n this.x = x\n this.y = y\n this.image = image\n }\n\n async commandForLanguage(language: PrinterLanguage, _config?: PrintConfig | undefined): Promise<Command> {\n return await this.commandGeneratorFor(language).image(this.image, this.x, this.y)\n }\n\n /**\n * Create an image field for an image\n * @param image \n * @param x \n * @param y \n * @param width \n * @param height \n * @returns \n */\n static async create(image: string|Blob, x: number, y: number, width?: number, height?: number): Promise<Image> {\n const bitmap = await ImageUtils.getBWBitmap(image, width, height)\n\n return new Image(x, y, bitmap)\n }\n}","import { Command, PrinterLanguage } from \"@/commands\";\nimport { PrintConfig } from \"../Printable\";\nimport LabelField from \"./LabelField\";\n\nexport default class QRCode extends LabelField {\n private readonly content: string\n private readonly x: number\n private readonly y: number\n private readonly width: number\n\n constructor(content: string, x: number, y: number, width: number) {\n super()\n this.content = content\n this.x = x\n this.y = y\n this.width = width\n }\n\n async commandForLanguage(language: PrinterLanguage, config?: PrintConfig | undefined): Promise<Command> {\n return await this.commandGeneratorFor(language).qrCode(this.content, this.width, this.x, this.y)\n }\n}","import { Command, PrinterLanguage } from \"@/commands\";\nimport { isWhitespace } from \"@/helpers/StringUtils\";\nimport LabelField from \"./LabelField\";\nimport Line from \"./Line\";\nimport Text from \"./Text\";\nimport { PrintConfig } from \"../Printable\";\nimport { FontOption } from \"../types\";\n\nexport type TableCellContent = string\n\nexport type TableSize = {\n width?: number,\n height?: number\n}\n\ntype SizeSpec = number|undefined\n\nexport type TableOptions = {\n size?: TableSize,\n columnWidths?: SizeSpec[],\n rowHeights?: SizeSpec[],\n lineThickness?: number,\n cellPadding?: number,\n formatted?: boolean,\n font?: FontOption\n}\n\nexport default class Table extends LabelField {\n private readonly x: number\n private readonly y: number\n private readonly rows: TableCellContent[][]\n\n private size: TableSize|undefined\n private columnWidths: SizeSpec[]|undefined\n private rowHeights: SizeSpec[]|undefined\n\n private lineThickness: number\n private cellPadding: number\n private formatted: boolean\n private font: FontOption\n\n constructor(x: number, y: number, rows: TableCellContent[][], options: TableOptions = {}) {\n super()\n this.x = x\n this.y = y\n this.rows = rows\n\n this.size = options.size\n this.columnWidths = options.columnWidths\n this.rowHeights = options.rowHeights\n this.lineThickness = options.lineThickness ?? 2\n this.cellPadding = options.cellPadding ?? 4\n this.formatted = options.formatted ?? true\n this.font = options.font ?? {name: \"default\", size: 10}\n }\n\n setSize(size: TableSize) {\n this.size = size\n }\n\n setColumnWidths(widths: SizeSpec[]) {\n this.columnWidths = widths\n }\n\n setRowHeights(heights: SizeSpec[]) {\n this.rowHeights = heights\n }\n\n setLineThickness(thickness: number) {\n this.lineThickness = thickness\n }\n\n setCellPadding(padding: number) {\n this.cellPadding = padding\n }\n\n setFormatted(formatted: boolean) {\n this.formatted = formatted\n }\n\n setFont(font: FontOption) {\n this.font = font\n }\n\n async commandForLanguage(language: PrinterLanguage, config?: PrintConfig): Promise<Command> {\n // Table rendering is implemented by composing existing primitives:\n // - Text fields for cell contents\n // - Line fields for the grid\n const generator = this.commandGeneratorFor(language)\n\n const rowCount = this.rows.length\n const colCount = Math.max(0, ...this.rows.map(r => r.length))\n\n // Resolve column widths.\n // If the overall table width is provided, unspecified columns share the remaining width.\n // Otherwise, unspecified columns are measured from content.\n const resolvedColumnWidths = this.resolveTrackSizes({\n trackCount: colCount,\n explicitSizes: this.columnWidths,\n total: this.size?.width,\n measure: (i) => this.measureAutoColumnWidth(i, colCount, config)\n })\n\n // Resolve row heights.\n // If the overall table height is provided, unspecified rows share the remaining height.\n // Otherwise, unspecified rows are measured from content and the resolved column widths.\n const resolvedRowHeights = this.resolveTrackSizes({\n trackCount: rowCount,\n explicitSizes: this.rowHeights,\n total: this.size?.height,\n measure: (i) => this.measureAutoRowHeight(i, resolvedColumnWidths, config)\n })\n\n // Convert widths/heights into absolute X/Y positions.\n const xPositions = this.accumulatePositions(this.x, resolvedColumnWidths)\n const yPositions = this.accumulatePositions(this.y, resolvedRowHeights)\n\n // We generate an internal list of LabelFields and then group their commands.\n // This ensures we reuse the exact behavior of the existing Text and Line fields.\n const fields: LabelField[] = []\n\n // Create a Text field for each cell.\n // Cell text is constrained to the cell content box, which enables wrapping.\n for(let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\n for(let colIndex = 0; colIndex < colCount; colIndex++) {\n const cellContent = this.rows[rowIndex]?.[colIndex] ?? \"\"\n const cellX = xPositions[colIndex]\n const cellY = yPositions[rowIndex]\n const cellWidth = resolvedColumnWidths[colIndex]\n const cellHeight = resolvedRowHeights[rowIndex]\n\n // Apply padding so text doesn't touch grid lines.\n const textX = cellX + this.cellPadding\n const textY = cellY + this.cellPadding\n const textWidth = Math.max(1, cellWidth - (this.cellPadding * 2))\n const textHeight = Math.max(1, cellHeight - (this.cellPadding * 2))\n\n const text = new Text(cellContent, textX, textY, this.formatted)\n text.setFont(this.font)\n // Multi-line text behavior matches the existing Text field:\n // - wraps when width is exceeded\n // - clips once the height constraint is reached\n text.setMultiLine(textWidth, textHeight)\n fields.push(text)\n }\n }\n\n // Total table dimensions (after resolving track sizes).\n const totalWidth = resolvedColumnWidths.reduce((a, b) => a + b, 0)\n const totalHeight = resolvedRowHeights.reduce((a, b) => a + b, 0)\n\n // Vertical grid lines (including left and right borders).\n for(let colIndex = 0; colIndex <= colCount; colIndex++) {\n const sx = colIndex == colCount ? this.x + totalWidth : xPositions[colIndex]\n fields.push(new Line(\n {x: sx, y: this.y},\n {x: sx, y: this.y + totalHeight},\n this.lineThickness\n ))\n }\n\n // Horizontal grid lines (including top and bottom borders).\n for(let rowIndex = 0; rowIndex <= rowCount; rowIndex++) {\n const sy = rowIndex == rowCount ? this.y + totalHeight : yPositions[rowIndex]\n fields.push(new Line(\n {x: this.x, y: sy},\n {x: this.x + totalWidth, y: sy},\n this.lineThickness\n ))\n }\n\n // Finally, generate and group all underlying commands.\n const commandList = await Promise.all(fields.map(field => field.commandForLanguage(language, config)))\n return generator.commandGroup(commandList)\n }\n\n private accumulatePositions(start: number, sizes: number[]): number[] {\n // Converts a list of track sizes (widths/heights) into absolute positions.\n // Returned array contains the starting coordinate for each track.\n const positions: number[] = []\n let current = start\n for(const s of sizes) {\n positions.push(current)\n current += s\n }\n return positions\n }\n\n private resolveTrackSizes(params: {\n trackCount: number,\n explicitSizes?: SizeSpec[],\n total?: number,\n measure: (trackIndex: number) => number\n }): number[] {\n if(params.trackCount == 0) return []\n \n // Resolves row/column sizes.\n // - If an explicit size is provided, it is used.\n // - If overall total is provided, any unspecified tracks share remaining space equally.\n // - Otherwise, unspecified tracks are measured from content.\n const sizes: SizeSpec[] = new Array(params.trackCount).fill(undefined)\n\n if(params.explicitSizes) {\n for(let i = 0; i < Math.min(params.trackCount, params.explicitSizes.length); i++) {\n sizes[i] = params.explicitSizes[i]\n }\n }\n\n if(params.total != undefined) {\n // Fixed + flexible: distribute remaining space among tracks with undefined size.\n const fixedTotal = sizes.reduce((sum: number, s) => sum + (s ?? 0), 0)\n const flexibleCount = sizes.filter(s => s == undefined).length\n\n const remaining = Math.max(0, params.total - fixedTotal)\n const flexSize = flexibleCount == 0 ? 0 : remaining / flexibleCount\n\n return sizes.map((s, i) => Math.max(1, s ?? flexSize ?? params.measure(i)))\n }\n\n return sizes.map((s, i) => Math.max(1, s ?? params.measure(i)))\n }\n\n private measureAutoColumnWidth(columnIndex: number, colCount: number, config?: PrintConfig): number {\n // Content-based width measurement for an auto-sized column.\n // This is a heuristic: it uses single-line text width + padding.\n const contentWidths: number[] = []\n\n for(const row of this.rows) {\n const content = row?.[columnIndex] ?? \"\"\n const plain = this.toPlainText(content)\n const w = this.textWidth(plain, config)\n contentWidths.push(w)\n }\n\n const maxContentWidth = contentWidths.length == 0 ? 0 : Math.max(...contentWidths)\n\n const minWidth = this.font.size\n const measured = Math.max(minWidth, maxContentWidth) + (this.cellPadding * 2)\n\n if(colCount == 0) return measured\n return measured\n }\n\n private measureAutoRowHeight(rowIndex: number, columnWidths: number[], config?: PrintConfig): number {\n // Content-based height measurement for an auto-sized row.\n // We estimate how many wrapped lines are needed for each cell, then take the max.\n const row = this.rows[rowIndex] ?? []\n const contentHeights: number[] = []\n\n for(let colIndex = 0; colIndex < columnWidths.length; colIndex++) {\n const content = row[colIndex] ?? \"\"\n const plain = this.toPlainText(content)\n const availableWidth = Math.max(1, columnWidths[colIndex] - (this.cellPadding * 2))\n const lineCount = this.estimateLineCount(plain, availableWidth, config)\n const lineHeight = this.font.size + 1\n contentHeights.push(lineCount * lineHeight)\n }\n\n const maxContentHeight = contentHeights.length == 0 ? this.font.size : Math.max(...contentHeights)\n return maxContentHeight + (this.cellPadding * 2)\n }\n\n private estimateLineCount(content: string, width: number, config?: PrintConfig): number {\n // Estimates wrapped line count using word-wrapping.\n // This doesn't try to exactly match printer rendering; it exists to auto-size rows.\n const normalized = content.replace(\"\\n\", \" \")\n\n if(normalized.trim() == \"\") return 1\n\n const words: string[] = []\n let buffer = \"\"\n\n for(let i = 0; i < normalized.length; i++) {\n const ch = normalized.charAt(i)\n if(isWhitespace(ch)) {\n if(buffer != \"\") {\n words.push(buffer)\n buffer = \"\"\n }\n continue\n }\n buffer += ch\n }\n\n if(buffer != \"\") words.push(buffer)\n\n let lines = 1\n let currentLine = \"\"\n\n for(const word of words) {\n const candidate = currentLine == \"\" ? word : `${currentLine} ${word}`\n\n if(this.textWidth(candidate, config) <= width) {\n currentLine = candidate\n } else {\n if(currentLine == \"\") {\n const charsPerLine = Math.max(1, Math.floor(width / Math.max(1, this.font.size)))\n const neededLines = Math.ceil(word.length / charsPerLine)\n lines += neededLines - 1\n currentLine = word.substring((neededLines - 1) * charsPerLine)\n } else {\n lines += 1\n currentLine = word\n }\n }\n }\n\n return Math.max(1, lines)\n }\n\n private textWidth(text: string, config?: PrintConfig): number {\n // Measures text width in dots.\n // If a font is registered and PrintConfig is provided, use accurate font metrics.\n // Otherwise fall back to a simple monospace approximation.\n if(this.font.name == \"default\" || !config) {\n return text.length * this.font.size\n }\n return config.textWidth(text, this.font)\n }\n\n private toPlainText(content: string): string {\n // Measurement helpers should ignore formatting.\n // This strips basic HTML tags used by the Text field's formatting support.\n return content.replace(/<[^>]*>/g, \"\")\n }\n}\n"],"mappings":"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","names":["pointsPerInch","buffer","image","target","src","imageData","buffer","url","image","target","bytes","bitmap","widthDots","bitmap","image","image","bytes","bytes","stringHelper","bytes","buffer","factory","Image","Image","image","bitmap","buffer"]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/index.ts","../src/commands/Command.ts","../src/commands/CommandGroup.ts","../src/commands/tspl/index.ts","../src/commands/tspl/TSPLCommand.ts","../src/commands/tspl/commands/TSPLRawCommand.ts","../src/commands/tspl/commands/TSPLCommandGroup.ts","../src/commands/tspl/commands/TSPLVisualCommand.ts","../src/helpers/UnitUtils.ts","../src/helpers/ImageDataParser.ts","../src/helpers/ImageProcessor.ts","../src/helpers/ImageUtils.ts","../src/commands/tspl/commands/basic/TSPLBitmapCommand.ts","../src/commands/tspl/types.ts","../src/commands/tspl/commands/basic/TSPLTextCommand.ts","../src/commands/tspl/commands/basic/TSPLGapCommand.ts","../src/commands/tspl/commands/basic/TSPLSizeCommand.ts","../src/commands/tspl/commands/basic/TSPLCLSCommand.ts","../src/commands/tspl/commands/basic/TSPLDirectionCommand.ts","../src/commands/tspl/commands/basic/TSPLPrintCommand.ts","../src/commands/tspl/commands/basic/TSPLBarCommand.ts","../src/commands/tspl/commands/basic/TSPLQRCommand.ts","../src/commands/tspl/commands/basic/TSPLBlockCommand.ts","../src/commands/tspl/commands/basic/TSPLDownload.ts","../src/commands/tspl/commands/basic/TSPLDisplay.ts","../src/commands/tspl/commands/basic/TSPLDiagonal.ts","../src/commands/tspl/commands/basic/TSPLBarcodeCommand.ts","../src/helpers/QRCodeUtils.ts","../src/commands/tspl/TSPLCommandGenerator.ts","../src/printers/index.ts","../src/printers/Printer.ts","../src/helpers/StringUtils.ts","../src/helpers/USBUtils.ts","../src/helpers/NetworkDevice.ts","../src/helpers/BonjourUtils.ts","../src/printers/TSPLPrinter.ts","../src/printers/PrinterService.ts","../src/labels/index.ts","../src/labels/Printable.ts","../src/labels/Label.ts","../src/labels/fields/LabelField.ts","../src/labels/fields/Line.ts","../src/labels/fields/Text.ts","../src/labels/fields/BarCode.ts","../src/labels/fields/Image.ts","../src/labels/fields/QRCode.ts","../src/labels/fields/Table.ts"],"sourcesContent":["export { default as Command } from \"./Command\"\nexport { default as CommandGroup } from \"./CommandGroup\"\n\nexport type PrinterLanguage = \"tspl\"\nexport type UnitSystem = \"imperial\"|\"metric\"|\"dot\"\n\nexport * as tspl from \"./tspl\"\nexport * from \"./types\"","import Device from \"@/helpers/Device\"\n\n/**\n * Base implementation for all types of command\n * Represents a command to be send to the printer to execute, such as print\n */\nexport default abstract class Command {\n /**\n * Returns a string representation of the command\n */\n abstract get commandString(): string\n\n print(fn: (command: string) => void) {\n fn(this.commandString)\n }\n\n /**\n * Write the command data to a device\n * @param device Device to write to\n */\n async writeTo(device: Device): Promise<void> {\n await this.writeString(this.commandString, device)\n await this.terminateCommand(device)\n }\n\n /**\n * Byte representation of a newline\n */\n protected get commandTerminatorBytes(): Uint8Array {\n return new Uint8Array([10])\n }\n\n /**\n * Writes a string to a device\n * @param data String representation of data\n * @param device Device to write to\n */\n protected async writeString(data: string, device: Device): Promise<void> {\n await device.writeString(data)\n }\n\n /**\n * Writes bytes to a device. It will automatically end a command with @see{commandTerminatorBytes}\n * @param data Byte array to send\n * @param device Device to write to\n */\n protected async writeBytes(data: Uint8Array|ArrayBuffer, device: Device): Promise<void> {\n await device.writeData(data)\n }\n\n /**\n * Write the command terminator to the device\n * @param device \n */\n protected async terminateCommand(device: Device): Promise<void> {\n await this.writeBytes(this.commandTerminatorBytes, device)\n }\n}","import Device from \"@/helpers/Device\";\nimport Command from \"./Command\";\n\n/**\n * A utility class that helps grouping commands together\n * Should be implemented with a specific command type to ensure only commands for the same language are\n * grouped together\n */\nexport default abstract class CommandGroup<T extends Command> extends Command {\n private commands: T[]\n\n constructor(commands: T[]) {\n super()\n this.commands = commands\n }\n\n print(fn: (command: string) => void) {\n for (let commandIndex in this.commands) {\n this.commands[commandIndex].print(fn)\n }\n }\n\n async writeTo(device: Device): Promise<void> {\n for (let commandIndex in this.commands) {\n await this.commands[commandIndex].writeTo(device)\n }\n }\n\n get commandString(): string {\n return this.commands.map(c => c.commandString).join(\"\\n\")\n }\n}","export { default as TSPLCommand } from \"./TSPLCommand\"\nexport { default as commandGenerator } from \"./TSPLCommandGenerator\"\n\nexport * from \"./commands\"\nexport * from \"./types\"","import Command from \"@/commands/Command\";\n\n/**\n * Base for TSPL specific commands\n */\nexport default abstract class TSPLCommand extends Command {\n}","import TSPLCommand from \"../TSPLCommand\"\n\n/**\n * A raw TSPL command. Can be used to use a command that is not yet supported\n */\nexport default class TSPLRawCommand extends TSPLCommand {\n /**\n * Raw command string\n */\n private readonly commandBody: string\n\n /**\n * Initialize a command with a raw body\n * @param body\n */\n constructor(body: string) {\n super()\n this.commandBody = body\n }\n\n get commandString(): string {\n return this.commandBody;\n }\n}\n","import CommandGroup from \"@/commands/CommandGroup\";\nimport TSPLCommand from \"../TSPLCommand\";\n\n/**\n * Command group for tspl commands\n */\nexport default class TSPLCommandGroup extends CommandGroup<TSPLCommand> {}","import TSPLCommand from \"../TSPLCommand\";\n\n/**\n * Base for all TSPL commands that have a visual effect on the final label\n */\nexport default abstract class TSPLVisualCommand extends TSPLCommand {\n protected readonly x: number\n protected readonly y: number\n\n constructor(x: number, y: number) {\n super()\n this.x = x\n this.y = y\n }\n}","import { UnitSystem } from \"@/commands\"\n\nconst pointsPerInch = 72\n\nexport function getSizePreserveAspect(width: number, height: number, desiredWidth?: number, desiredHeight?: number) {\n // 0 width or height is not a valid number so we filter those dogether with undefined or null values\n if(desiredHeight && desiredWidth) {\n return { width: desiredWidth, height: desiredHeight }\n }\n if(desiredHeight) {\n const scaleFactor = desiredHeight / height\n return { width: width * scaleFactor, height: desiredHeight }\n } else if (desiredWidth) {\n const scaleFactor = desiredWidth / width\n return { width: desiredWidth, height: height * scaleFactor }\n } else {\n return { width, height }\n }\n}\n\nexport function valueWithUnit(value: number, unitSystem: UnitSystem) {\n switch(unitSystem) {\n case \"dot\": return `${value} dot`\n case \"imperial\": return value\n case \"metric\": return `${value} mm`\n }\n}\n\n/**\n * Convert a value from dots in points in a given dpi\n */\nexport function dotToPoint(dots: number, dpi: number): number {\n const inch = dots / dpi\n return Math.round(inch * pointsPerInch)\n}\n\n/**\n * Converts the points value to dots\n * 1 inch = 72 points (standard in typography)\n * Formula: dots = points * dpi / pointsPerInch\n * @param points \n * @param dpi \n * @returns \n */\nexport function pointsToDots(points: number, dpi: number): number {\n const pointsPerInch = 72;\n const dots = points * dpi / pointsPerInch;\n return dots;\n}","\n\nexport interface ImageData {\n width: number;\n height: number;\n data: Uint8Array;\n bitsPerPixel: number;\n}\n\nexport function parsePNG(buffer: Buffer): ImageData {\n const pngSignature = Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]);\n if (!buffer.subarray(0, 8).equals(pngSignature)) {\n throw new Error('Invalid PNG file');\n }\n\n let width = 0, height = 0, bitDepth = 0, colorType = 0;\n let compressionMethod = 0, filterMethod = 0, interlaceMethod = 0;\n let palette: Buffer | null = null;\n let transparency: Buffer | null = null; // <-- Add this\n let idatChunks: Buffer[] = [];\n\n let offset = 8;\n while (offset < buffer.length) {\n const chunkLength = buffer.readUInt32BE(offset);\n const chunkType = buffer.subarray(offset + 4, offset + 8).toString('ascii');\n const chunkData = buffer.subarray(offset + 8, offset + 8 + chunkLength);\n\n if (chunkType === 'IHDR') {\n width = chunkData.readUInt32BE(0);\n height = chunkData.readUInt32BE(4);\n bitDepth = chunkData.readUInt8(8);\n colorType = chunkData.readUInt8(9);\n compressionMethod = chunkData.readUInt8(10);\n filterMethod = chunkData.readUInt8(11);\n interlaceMethod = chunkData.readUInt8(12);\n } else if (chunkType === 'PLTE') {\n palette = chunkData;\n } else if (chunkType === 'tRNS') {\n transparency = chunkData;\n } else if (chunkType === 'IDAT') {\n idatChunks.push(chunkData);\n } else if (chunkType === 'IEND') {\n break;\n }\n offset += 8 + chunkLength + 4; // chunk header + data + CRC\n }\n\n if (compressionMethod !== 0) throw new Error('Unsupported PNG compression method');\n if (filterMethod !== 0) throw new Error('Unsupported PNG filter method');\n if (interlaceMethod !== 0) throw new Error('Interlaced PNGs not supported');\n if (idatChunks.length === 0) throw new Error('No image data found in PNG');\n\n const compressedData = Buffer.concat(idatChunks);\n let decompressedData: Buffer;\n try {\n const zlib = require('zlib');\n decompressedData = zlib.inflateSync(compressedData);\n } catch (error) {\n throw new Error('Failed to decompress PNG data: ' + error);\n }\n\n if (bitDepth !== 8) throw new Error('Only 8-bit PNGs are supported in this parser');\n\n let bytesPerPixel: number;\n let channels: number;\n let outputChannels = 4;\n switch (colorType) {\n case 0: channels = 1; bytesPerPixel = 1; break; // Grayscale\n case 2: channels = 3; bytesPerPixel = 3; break; // RGB\n case 3: channels = 1; bytesPerPixel = 1; break; // Palette\n case 4: channels = 2; bytesPerPixel = 2; break; // Grayscale+Alpha\n case 6: channels = 4; bytesPerPixel = 4; break; // RGBA\n default: throw new Error(`Unsupported PNG color type: ${colorType}`);\n }\n\n const scanlineLength = width * bytesPerPixel;\n const data = new Uint8Array(width * height * outputChannels);\n\n // PNG filters are applied relative to the *unfiltered* previous scanline.\n // Keep the previous unfiltered scanline buffer to decode correctly.\n let prevUnfilteredScanline: Buffer = Buffer.alloc(scanlineLength);\n\n for (let y = 0; y < height; y++) {\n const scanlineStart = y * (scanlineLength + 1);\n const filterType = decompressedData[scanlineStart];\n const scanline = decompressedData.subarray(scanlineStart + 1, scanlineStart + 1 + scanlineLength);\n\n const unfilteredScanline = applyPNGFilter(filterType, scanline, prevUnfilteredScanline, bytesPerPixel);\n prevUnfilteredScanline = unfilteredScanline as Buffer;\n\n for (let x = 0; x < width; x++) {\n const outIdx = (y * width + x) * outputChannels;\n\n if (colorType === 0) { // Grayscale\n const gray = unfilteredScanline[x];\n data[outIdx] = gray;\n data[outIdx + 1] = gray;\n data[outIdx + 2] = gray;\n data[outIdx + 3] = 255;\n } else if (colorType === 2) { // RGB\n data[outIdx] = unfilteredScanline[x * 3];\n data[outIdx + 1] = unfilteredScanline[x * 3 + 1];\n data[outIdx + 2] = unfilteredScanline[x * 3 + 2];\n data[outIdx + 3] = 255;\n } else if (colorType === 3) { // Palette\n if (!palette) throw new Error('Palette PNG missing PLTE chunk');\n const idx = unfilteredScanline[x];\n data[outIdx] = palette[idx * 3];\n data[outIdx + 1] = palette[idx * 3 + 1];\n data[outIdx + 2] = palette[idx * 3 + 2];\n data[outIdx + 3] = transparency && idx < transparency.length ? transparency[idx] : 255;\n } else if (colorType === 4) { // Grayscale + Alpha\n const gray = unfilteredScanline[x * 2];\n data[outIdx] = gray;\n data[outIdx + 1] = gray;\n data[outIdx + 2] = gray;\n data[outIdx + 3] = unfilteredScanline[x * 2 + 1];\n } else if (colorType === 6) { // RGBA\n data[outIdx] = unfilteredScanline[x * 4];\n data[outIdx + 1] = unfilteredScanline[x * 4 + 1];\n data[outIdx + 2] = unfilteredScanline[x * 4 + 2];\n data[outIdx + 3] = unfilteredScanline[x * 4 + 3];\n }\n }\n }\n\n return {\n data,\n width,\n height,\n bitsPerPixel: outputChannels\n };\n}\n/**\n * Apply PNG filter to scanline\n * @param filterType PNG filter type (0-4)\n * @param scanline Current scanline data\n * @param prevScanline Previous scanline data\n * @param bytesPerPixel Bytes per pixel\n * @returns Unfiltered scanline\n */\nfunction applyPNGFilter(filterType: number, scanline: Buffer, prevScanline: Buffer, bytesPerPixel: number): Buffer {\n const result = Buffer.alloc(scanline.length);\n\n for (let i = 0; i < scanline.length; i++) {\n let filtered = scanline[i];\n let a = i >= bytesPerPixel ? result[i - bytesPerPixel] : 0; // Left pixel\n let b = prevScanline[i] || 0; // Above pixel\n let c = (i >= bytesPerPixel && prevScanline[i - bytesPerPixel]) ? prevScanline[i - bytesPerPixel] : 0; // Above-left pixel\n \n switch (filterType) {\n case 0: // None\n result[i] = filtered;\n break;\n case 1: // Sub\n result[i] = (filtered + a) & 0xFF;\n break;\n case 2: // Up\n result[i] = (filtered + b) & 0xFF;\n break;\n case 3: // Average\n result[i] = (filtered + Math.floor((a + b) / 2)) & 0xFF;\n break;\n case 4: // Paeth\n const p = a + b - c;\n const pa = Math.abs(p - a);\n const pb = Math.abs(p - b);\n const pc = Math.abs(p - c);\n let paeth;\n if (pa <= pb && pa <= pc) {\n paeth = a;\n } else if (pb <= pc) {\n paeth = b;\n } else {\n paeth = c;\n }\n result[i] = (filtered + paeth) & 0xFF;\n break;\n default:\n result[i] = filtered;\n }\n }\n\n return result;\n}\n","/**\n * Cross-platform image processing utility that works in both browser and Node.js environments\n * Replaces the need for the 'image-pixels' package\n * Supports local files, data URLs, Blobs, and remote URLs\n */\nimport { ImageData, parsePNG } from './ImageDataParser';\n\nexport class ImageProcessor {\n /**\n * Get pixel information about an image\n * @param image Image to process (local file path, remote URL, data URL, or Blob)\n * @param target Optional target raster size. Useful for vector inputs (e.g. SVG) to rasterize at the final size.\n * @returns Promise with image data including width, height, pixel data, and bits per pixel\n */\n static async getImageData(image: string | Blob, target?: { width: number; height: number }): Promise<ImageData> {\n if (typeof window !== 'undefined') {\n return this.getImageDataBrowser(image, target);\n } else {\n return this.getImageDataNode(image, target);\n }\n }\n\n /******** BROWSER ********/\n\n /**\n * Get pixel information about an image in browser environment\n * @param image Image to process\n * @param target Optional target raster size.\n * @returns Promise with image data\n */\n private static async getImageDataBrowser(image: string | Blob, target?: { width: number; height: number }): Promise<ImageData> {\n const loadImage = (src: string): Promise<HTMLImageElement> => {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.crossOrigin = 'anonymous';\n img.onload = () => resolve(img);\n img.onerror = () => reject(new Error('Failed to load image'));\n img.src = src;\n });\n }\n\n let src: string\n let revokeUrl: string | undefined\n\n if (typeof image === 'string') {\n src = this.normalizePotentialSVGSource(image)\n } else {\n revokeUrl = URL.createObjectURL(image)\n src = revokeUrl\n }\n\n try {\n const img = await loadImage(src)\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n\n if (!ctx) {\n throw new Error('Could not get canvas context')\n }\n\n const width = target?.width ?? img.width\n const height = target?.height ?? img.height\n\n canvas.width = width;\n canvas.height = height;\n\n ctx.drawImage(img, 0, 0, width, height);\n const imageData = ctx.getImageData(0, 0, width, height);\n\n return {\n data: new Uint8Array(imageData.data),\n width,\n height,\n bitsPerPixel: 4,\n }\n } finally {\n if (revokeUrl) URL.revokeObjectURL(revokeUrl)\n }\n }\n\n /******** NODEJS ********/\n\n /**\n * Get pixel information about an image in Node.js environment\n * @param image Image to process\n * @param target Optional target raster size.\n * @returns Promise with image data\n */\n private static async getImageDataNode(image: string | Blob, _target?: { width: number; height: number }): Promise<ImageData> {\n console.log('Processing image in Node.js environment');\n // For Node.js, we'll use a simple approach with built-in modules\n if (image instanceof Blob) {\n throw new Error('Blob input not supported in Node.js environment. Use file path or data URL instead.');\n }\n\n const trimmed = image.trim()\n if (trimmed.startsWith('<svg')) {\n return this.rasterizeSVGNode(trimmed, _target)\n }\n \n // Check if it's a data URL\n if (image.startsWith('data:')) {\n return this.getImageFromData(image, _target);\n } else if (image.startsWith('http://') || image.startsWith('https://')) {\n return this.getImageFromUrl(image, _target);\n } else {\n return this.getImageFromFile(image, _target);\n }\n }\n\n /**\n * Parse a data URL to extract image data\n * @param dataURL Data URL string\n * @returns Promise with image data\n */\n private static async getImageFromData(dataURL: string, target?: { width: number; height: number }): Promise<ImageData> {\n const [header, data] = dataURL.split(',');\n const mimeType = header.match(/data:([^;]+)/)?.[1];\n \n if (!mimeType?.startsWith('image/')) {\n throw new Error('Invalid image data URL');\n }\n \n const extension = mimeType.split('/')[1].toLowerCase();\n if (extension === 'svg+xml' || mimeType === 'image/svg+xml') {\n const isBase64 = header.includes(';base64')\n const svgText = isBase64\n ? Buffer.from(data, 'base64').toString('utf8')\n : decodeURIComponent(data)\n return this.rasterizeSVGNode(svgText, target)\n }\n\n const buffer = Buffer.from(data, 'base64');\n return this.parse(buffer, extension);\n }\n\n /**\n * Image data from file\n * @param image \n * @returns \n */\n private static async getImageFromFile(image: string, target?: { width: number; height: number }): Promise<ImageData> {\n const fs = await eval(\"require\")('fs');\n const path = await eval(\"require\")('path');\n \n if (!fs.existsSync(image)) {\n throw new Error(`Image file not found: ${image}`);\n }\n \n const buffer = fs.readFileSync(image);\n const ext = path.extname(image).toLowerCase();\n\n if (ext === '.svg') {\n const svgText = buffer.toString('utf8')\n return this.rasterizeSVGNode(svgText, target)\n }\n\n return this.parse(buffer, ext);\n }\n\n /**\n * Fetch and process a remote image in Node.js environment\n * @param url Remote image URL\n * @returns Promise with image data\n */\n private static async getImageFromUrl(url: string, target?: { width: number; height: number }): Promise<ImageData> {\n // Use dynamic import to support both Node.js versions\n let fetch: any;\n try {\n // Try to use built-in fetch (Node.js 18+)\n fetch = globalThis.fetch;\n } catch {\n // Use https module as fallback\n return this.fetchWithHttps(url, target);\n }\n\n if (!fetch) {\n return this.fetchWithHttps(url, target);\n }\n\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch image: ${response.status} ${response.statusText}`);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n const buffer = Buffer.from(arrayBuffer);\n \n // Determine image type from content or URL\n const contentType = response.headers.get('content-type');\n const imageType = this.getImageType(contentType || '', url);\n\n if (imageType === 'svg') {\n const svgText = buffer.toString('utf8')\n return this.rasterizeSVGNode(svgText, target)\n }\n\n return this.parse(buffer, imageType);\n }\n\n /**\n * Fetch remote image using Node.js https module (fallback)\n * @param url Remote image URL\n * @returns Promise with image data\n */\n private static async fetchWithHttps(url: string, target?: { width: number; height: number }): Promise<ImageData> {\n const https = await eval(\"require\")('https');\n const http = await eval(\"require\")('http');\n \n return new Promise((resolve, reject) => {\n const client = url.startsWith('https:') ? https : http;\n \n const request = client.get(url, (response: any) => {\n if (response.statusCode !== 200) {\n reject(new Error(`Failed to fetch image: ${response.statusCode} ${response.statusMessage}`));\n return;\n }\n \n const chunks: Buffer[] = [];\n \n response.on('data', (chunk: any) => {\n chunks.push(chunk);\n });\n \n response.on('end', () => {\n try {\n const buffer = Buffer.concat(chunks);\n \n // Determine image type from content-type header or URL\n const contentType = response.headers['content-type'] || '';\n const imageType = this.getImageType(contentType || '', url);\n\n if (imageType === 'svg') {\n const svgText = buffer.toString('utf8')\n resolve(this.rasterizeSVGNode(svgText, target))\n return\n }\n\n resolve(this.parse(buffer, imageType))\n } catch (error) {\n reject(error);\n }\n });\n \n response.on('error', (error: any) => {\n reject(error);\n });\n });\n \n request.on('error', (error: any) => {\n reject(new Error(`Failed to fetch remote image: ${error.message}`));\n });\n \n request.setTimeout(30000, () => {\n request.destroy();\n reject(new Error('Request timeout: Failed to fetch remote image within 30 seconds'));\n });\n });\n }\n\n /**\n * Decide content type\n */\n private static getImageType(contentType: string, url: string): string {\n if (contentType) {\n if (contentType.includes('png')) {\n return 'png';\n } else if (contentType.includes('jpeg') || contentType.includes('jpg')) {\n return 'jpeg';\n } else if (contentType.includes('svg')) {\n return 'svg';\n }\n }\n \n const urlLower = url.toLowerCase();\n if (urlLower.includes('.png')) {\n return 'png';\n } else if (urlLower.includes('.jpg') || urlLower.includes('.jpeg')) {\n return 'jpeg';\n } else if (urlLower.includes('.svg')) {\n return 'svg';\n }\n\n return \"\"\n }\n\n /**\n * Parse image data by extension\n */\n private static parse(buffer: Buffer, extension: string): ImageData {\n const normalizedExtension = extension.startsWith(\".\") ? extension.slice(1) : extension\n console.log(`Parsing image with extension: ${normalizedExtension}`);\n\n if (normalizedExtension === 'png') {\n return parsePNG(buffer);\n } else if (normalizedExtension === 'jpeg' || normalizedExtension === 'jpg') {\n return this.parseJPEG(buffer);\n } else if (normalizedExtension === 'svg') {\n // Note: In Node we don't reach this when loading SVG through the high-level APIs because we route\n // SVG through rasterizeSVGNode() first. Keeping this as a guard.\n throw new Error('svg-not-supported-in-node')\n } else {\n throw new Error(`Unsupported image format: ${normalizedExtension}. Supported formats: PNG, JPEG`);\n }\n }\n\n private static rasterizeSVGNode(svg: string, target?: { width: number; height: number }): ImageData {\n // TODO: This is Node-only. For best browser-safety this likely benefits from conditional exports so\n // browser bundlers don't attempt to include @resvg/resvg-js.\n let Resvg: any\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n Resvg = eval(\"require\")(\"@resvg/resvg-js\").Resvg\n } catch (_e) {\n throw new Error('svg-rasterizer-missing')\n }\n\n const fitTo = target\n ? { mode: 'width' as const, value: target.width }\n : undefined\n\n const resvg = new Resvg(svg, {\n fitTo,\n })\n\n const pngData: Uint8Array = resvg.render().asPng()\n const pngBuffer = Buffer.from(pngData)\n const imageData = parsePNG(pngBuffer)\n\n if (target && (imageData.width !== target.width || imageData.height !== target.height)) {\n return this.resize(imageData, target.width, target.height)\n }\n\n return imageData\n }\n\n private static normalizePotentialSVGSource(source: string): string {\n const trimmed = source.trim()\n const isInlineSvg = trimmed.startsWith('<svg')\n const isSvgDataUrl = trimmed.startsWith('data:image/svg+xml')\n\n if (isInlineSvg) {\n const encoded = encodeURIComponent(trimmed)\n return `data:image/svg+xml;charset=utf-8,${encoded}`\n }\n\n if (isSvgDataUrl) return source\n return source\n }\n\n private static parseJPEG(buffer: Buffer): ImageData {\n // JPEG signature check\n if (buffer[0] !== 0xFF || buffer[1] !== 0xD8) {\n throw new Error('Invalid JPEG file');\n }\n \n let offset = 2;\n let width = 0;\n let height = 0;\n \n // Look for SOF (Start of Frame) marker to get dimensions\n while (offset < buffer.length - 1) {\n if (buffer[offset] === 0xFF) {\n const marker = buffer[offset + 1];\n \n // SOF0, SOF1, SOF2 markers\n if (marker >= 0xC0 && marker <= 0xC2) {\n height = buffer.readUInt16BE(offset + 5);\n width = buffer.readUInt16BE(offset + 7);\n break;\n }\n \n // Skip to next marker\n if (offset + 2 < buffer.length) {\n const segmentLength = buffer.readUInt16BE(offset + 2);\n offset += 2 + segmentLength;\n } else {\n break;\n }\n } else {\n offset++;\n }\n }\n \n if (width === 0 || height === 0) {\n throw new Error('Could not determine JPEG dimensions');\n }\n \n // Create a meaningful placeholder pattern instead of random noise\n // This creates a gradient pattern that represents the image structure\n const pixelCount = width * height;\n const data = new Uint8Array(pixelCount * 4); // RGBA format\n \n // Calculate average color from file data for base color\n let avgR = 0, avgG = 0, avgB = 0;\n const sampleSize = Math.min(1000, buffer.length);\n for (let i = 0; i < sampleSize; i += 3) {\n avgR += buffer[i] || 0;\n avgG += buffer[i + 1] || 0;\n avgB += buffer[i + 2] || 0;\n }\n avgR = Math.floor(avgR / (sampleSize / 3));\n avgG = Math.floor(avgG / (sampleSize / 3));\n avgB = Math.floor(avgB / (sampleSize / 3));\n \n // Create a gradient pattern based on position and average colors\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const i = (y * width + x) * 4;\n \n // Create a gradient pattern\n const xRatio = x / width;\n const yRatio = y / height;\n \n // Mix the average color with a gradient\n const r = Math.floor(avgR * (0.5 + 0.5 * xRatio));\n const g = Math.floor(avgG * (0.5 + 0.5 * yRatio));\n const b = Math.floor(avgB * (0.5 + 0.5 * (xRatio + yRatio) / 2));\n \n data[i] = Math.min(255, Math.max(0, r)); // R\n data[i + 1] = Math.min(255, Math.max(0, g)); // G\n data[i + 2] = Math.min(255, Math.max(0, b)); // B\n data[i + 3] = 255; // A\n }\n }\n \n return {\n data,\n width,\n height,\n bitsPerPixel: 4\n };\n }\n\n /**\n * Convert image data to grayscale\n * @param imageData Original image data\n * @returns Grayscale image data\n */\n static toGrayscale(imageData: ImageData): ImageData {\n const { data, width, height } = imageData;\n const grayscaleData = new Uint8Array(data.length);\n \n for (let i = 0; i < data.length; i += 4) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const a = data[i + 3];\n \n // Calculate grayscale using luminance formula\n const gray = Math.round(0.299 * r + 0.587 * g + 0.114 * b);\n \n grayscaleData[i] = gray; // R\n grayscaleData[i + 1] = gray; // G\n grayscaleData[i + 2] = gray; // B\n grayscaleData[i + 3] = a; // A (preserve alpha)\n }\n \n return {\n data: grayscaleData,\n width,\n height,\n bitsPerPixel: imageData.bitsPerPixel\n };\n }\n\n /**\n * Resize image data (simple nearest neighbor algorithm)\n * @param imageData Original image data\n * @param newWidth Target width\n * @param newHeight Target height\n * @returns Resized image data\n */\n static resize(imageData: ImageData, newWidth: number, newHeight: number): ImageData {\n const { data, width, height, bitsPerPixel } = imageData;\n const resizedData = new Uint8Array(newWidth * newHeight * bitsPerPixel);\n \n const xRatio = width / newWidth;\n const yRatio = height / newHeight;\n \n for (let y = 0; y < newHeight; y++) {\n for (let x = 0; x < newWidth; x++) {\n const srcX = Math.floor(x * xRatio);\n const srcY = Math.floor(y * yRatio);\n \n const srcIndex = (srcY * width + srcX) * bitsPerPixel;\n const destIndex = (y * newWidth + x) * bitsPerPixel;\n \n for (let c = 0; c < bitsPerPixel; c++) {\n resizedData[destIndex + c] = data[srcIndex + c];\n }\n }\n }\n \n return {\n data: resizedData,\n width: newWidth,\n height: newHeight,\n bitsPerPixel\n };\n }\n}\n\nexport default ImageProcessor;\n","import { getSizePreserveAspect } from \"./UnitUtils\"\nimport ImageProcessor from \"./ImageProcessor\"\n\n/**\n * Helper type to transmit image bitmap data\n */\nexport type Pixels = {\n data: Uint8Array, \n width: number,\n height: number, \n bitsPerPixel: number\n}\n\nexport type BitmapLike = {\n width: number,\n height: number,\n bytes: Uint8Array\n}\n\n/**\n * Helper type to transmit black and white bitmap data\n */\nexport type BWBitmap = BitmapLike\n\nconst BLACK_PIXEL = 0\nconst WHITE_PIXEL = 1\nconst DEFAULT_THRESHOLD = 240\nconst DEFAULT_CROP_ALPHA_THRESHOLD = 16\n\n/**\n * Set of image utility\n */\nexport default class ImageUtils {\n /**\n * Get pixel information about an image\n * @param image Image to process\n * @param target Optional target raster size. Useful for vector inputs (e.g. SVG) to rasterize at the final size.\n * @returns \n */\n static async getPixels(image: string|Blob, target?: { width: number; height: number }): Promise<Pixels> {\n return await ImageProcessor.getImageData(image, target)\n }\n\n /**\n * Return a bitmap in which all pixels are represented with one bit of either 1 or 0 representing white and black\n * pixels respectively. `destinationWidth` and `destinationHeight` have to be smaller or equal to the\n * input size as only downscaling is performed\n * \n * @param image Image to process \n * @param destinationWidth Width of the output bitmap\n * @param destinationHeight Height of the output bitmap\n * @returns \n */\n static async getBWBitmap(\n image: string|Blob,\n destinationWidth?: number,\n destinationHeight?: number,\n threshold?: number,\n lsbFirst: boolean = false,\n ): Promise<BWBitmap> {\n const {\n data,\n width,\n height,\n bitsPerPixel\n } = await this.getPixels(\n image,\n destinationWidth != null && destinationHeight != null\n ? { width: destinationWidth, height: destinationHeight }\n : undefined\n )\n\n // Auto-crop transparent margins for RGBA sources so content isn't shrunk to a few pixels when resizing.\n // Only applies when alpha channel is present.\n let cropX0 = 0\n let cropY0 = 0\n let cropX1 = width - 1\n let cropY1 = height - 1\n\n if (bitsPerPixel > 3) {\n let found = false\n let minX = width\n let minY = height\n let maxX = -1\n let maxY = -1\n\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const a = data[(y * width * bitsPerPixel) + (x * bitsPerPixel) + 3]\n if (a >= DEFAULT_CROP_ALPHA_THRESHOLD) {\n found = true\n if (x < minX) minX = x\n if (y < minY) minY = y\n if (x > maxX) maxX = x\n if (y > maxY) maxY = y\n }\n }\n }\n\n if (found) {\n cropX0 = minX\n cropY0 = minY\n cropX1 = maxX\n cropY1 = maxY\n }\n }\n\n const cropWidth = cropX1 - cropX0 + 1\n const cropHeight = cropY1 - cropY0 + 1\n \n const dim = getSizePreserveAspect(cropWidth, cropHeight, destinationWidth, destinationHeight)\n // Number of pixels width and height => number of bits for each row and number of rows\n const dWidth = dim.width\n const dHeight = dim.height\n \n const differenceToDividable = dWidth % 8 == 0 ? 0 : (8 - (dWidth % 8))\n const dividableDWidth = dWidth + differenceToDividable\n\n // Luminance buffer for adaptive thresholding.\n // Stored per destination pixel (including padding), 0..255.\n const luminances = new Uint8Array(dividableDWidth * dHeight)\n\n let destinationIndex = 0\n for (let h=0; h < dHeight; h++) {\n const srcY0 = cropY0 + Math.floor((h * cropHeight) / dHeight)\n const srcY1 = Math.max(srcY0, cropY0 + Math.floor(((h + 1) * cropHeight) / dHeight) - 1)\n\n for(let w=0; w < dWidth; w++) {\n const srcX0 = cropX0 + Math.floor((w * cropWidth) / dWidth)\n const srcX1 = Math.max(srcX0, cropX0 + Math.floor(((w + 1) * cropWidth) / dWidth) - 1)\n\n let lumSum = 0\n let count = 0\n let opaqueCount = 0\n let opaqueLumSum = 0\n let opaqueWeightSum = 0\n let minOpaqueLum = 255\n\n for (let sy = srcY0; sy <= srcY1; sy++) {\n for (let sx = srcX0; sx <= srcX1; sx++) {\n const baseIndex = (sy * width * bitsPerPixel) + (sx * bitsPerPixel)\n\n const r = data[baseIndex]\n const g = data[baseIndex + 1]\n const b = data[baseIndex + 2]\n const a = bitsPerPixel > 3 ? data[baseIndex + 3] : 255\n\n // Composite onto white background first (important for antialiasing and transparent pixels)\n const alpha = a / 255\n const rC = r * alpha + 255 * (1 - alpha)\n const gC = g * alpha + 255 * (1 - alpha)\n const bC = b * alpha + 255 * (1 - alpha)\n\n lumSum += (0.299 * rC) + (0.587 * gC) + (0.114 * bC)\n count += 1\n\n if (a > 0) {\n opaqueCount += 1\n const lum = (0.299 * r) + (0.587 * g) + (0.114 * b)\n opaqueLumSum += lum * alpha\n opaqueWeightSum += alpha\n if (lum < minOpaqueLum) minOpaqueLum = lum\n }\n }\n }\n\n const avgLum = count > 0 ? (lumSum / count) : 255\n const avgOpaqueLum = opaqueWeightSum > 0 ? (opaqueLumSum / opaqueWeightSum) : 255\n const opaqueRatio = count > 0 ? (opaqueCount / count) : 0\n const luminance = opaqueCount === 0\n ? 255\n : (opaqueRatio < 0.25 ? minOpaqueLum : avgOpaqueLum)\n luminances[destinationIndex] = Math.max(0, Math.min(255, Math.round(luminance)))\n\n destinationIndex += 1\n }\n \n for(let i=0; i < differenceToDividable; i++) {\n luminances[destinationIndex] = 255\n destinationIndex += 1\n }\n }\n\n const thresholdValue = threshold ?? this.otsuThreshold(luminances, dWidth, dividableDWidth, dHeight)\n\n // Size of the array has to be with * height but width has to be extended to be dividable by 8\n const bitmapData = new Uint8Array(dividableDWidth * dHeight)\n for (let h = 0; h < dHeight; h++) {\n const rowOffset = h * dividableDWidth\n for (let w = 0; w < dividableDWidth; w++) {\n const idx = rowOffset + w\n bitmapData[idx] = luminances[idx] > thresholdValue ? WHITE_PIXEL : BLACK_PIXEL\n }\n }\n \n const byteArrays = this.chunk(bitmapData,8)\n const widthInBytes = dividableDWidth / 8\n \n const bytes = byteArrays.map((b) => this.bitsToByte(b, lsbFirst))\n const finalBytes = new Uint8Array(bytes)\n \n return {\n width: widthInBytes,\n height: dHeight,\n bytes: finalBytes\n }\n }\n\n private static otsuThreshold(luminances: Uint8Array, contentWidth: number, rowWidth: number, height: number): number {\n // Histogram of 0..255\n const hist = new Uint32Array(256)\n let total = 0\n\n for (let y = 0; y < height; y++) {\n const rowOffset = y * rowWidth\n for (let x = 0; x < contentWidth; x++) {\n hist[luminances[rowOffset + x]] += 1\n total += 1\n }\n }\n\n if (total === 0) return DEFAULT_THRESHOLD\n\n let sum = 0\n for (let t = 0; t < 256; t++) sum += t * hist[t]\n\n let sumB = 0\n let wB = 0\n let wF = 0\n let maxBetween = -1\n let threshold = DEFAULT_THRESHOLD\n\n for (let t = 0; t < 256; t++) {\n wB += hist[t]\n if (wB === 0) continue\n wF = total - wB\n if (wF === 0) break\n\n sumB += t * hist[t]\n\n const mB = sumB / wB\n const mF = (sum - sumB) / wF\n const between = wB * wF * (mB - mF) * (mB - mF)\n\n if (between > maxBetween) {\n maxBetween = between\n threshold = t\n }\n }\n\n return threshold\n }\n\n /**\n * Splits an array into chunks.\n * @param originalArray\n * @param chunkSize\n * @returns\n */\n private static chunk(originalArray: Uint8Array, chunkSize: number): Uint8Array[] {\n const resultArray = [];\n\n for (let i = 0; i < originalArray.length; i += chunkSize) {\n const chunk = originalArray.slice(i, i + chunkSize);\n resultArray.push(chunk);\n }\n\n return resultArray;\n }\n\n /**\n * Converts an array of bits to a byte\n * @param bits\n * @returns\n */\n private static bitsToByte(bits: Uint8Array, lsbFirst: boolean) {\n let byteValue = 0\n\n if (lsbFirst) {\n for (let i = 0; i < bits.length; i++) {\n byteValue |= (bits[i] & 1) << i\n }\n return byteValue\n }\n\n for (let i = 0; i < bits.length; i++) {\n byteValue = (byteValue << 1) | (bits[i] & 1)\n }\n return byteValue\n }\n\n static dilateBWBitmap(bitmap: BWBitmap, iterations: number = 1): BWBitmap {\n let current = bitmap\n for (let i = 0; i < iterations; i++) {\n current = this.dilateOnce(current)\n }\n return current\n }\n\n static bwBitmapToPBM(bitmap: BWBitmap, widthDots?: number): Uint8Array {\n const widthBytes = bitmap.width\n const height = bitmap.height\n const widthBits = widthDots ?? (widthBytes * 8)\n const header = `P4\\n${widthBits} ${height}\\n`\n\n const headerBytes = new TextEncoder().encode(header)\n\n // PBM P4 expects 1=black, 0=white, MSB-first in each byte.\n // Our BWBitmap uses 0=black, 1=white. So we invert bits.\n const rowBytes = Math.ceil(widthBits / 8)\n const out = new Uint8Array(headerBytes.length + rowBytes * height)\n out.set(headerBytes, 0)\n\n const src = bitmap.bytes\n let offset = headerBytes.length\n\n for (let y = 0; y < height; y++) {\n const rowStart = y * widthBytes\n for (let xb = 0; xb < rowBytes; xb++) {\n const b = src[rowStart + xb] ?? 0xff\n out[offset++] = (~b) & 0xff\n }\n\n // If widthDots is not byte-aligned, clear the unused bits in the last byte.\n const extraBits = (rowBytes * 8) - widthBits\n if (extraBits > 0) {\n const mask = 0xff << extraBits\n out[offset - 1] = out[offset - 1] & mask\n }\n }\n\n return out\n }\n\n static async saveBWBitmapAsPBM(bitmap: BWBitmap, filePath: string, widthDots?: number): Promise<void> {\n if (typeof window !== \"undefined\") {\n throw new Error(\"pbm-export-not-supported-in-browser\")\n }\n\n const fs = await eval(\"require\")(\"fs\")\n const bytes = this.bwBitmapToPBM(bitmap, widthDots)\n fs.writeFileSync(filePath, bytes)\n }\n\n private static dilateOnce(bitmap: BWBitmap): BWBitmap {\n const widthBytes = bitmap.width\n const widthBits = widthBytes * 8\n const height = bitmap.height\n\n const src = bitmap.bytes\n const dst = new Uint8Array(src.length)\n\n const getBit = (x: number, y: number): 0|1 => {\n if (x < 0 || y < 0 || x >= widthBits || y >= height) return 1\n const byteIndex = (y * widthBytes) + (x >> 3)\n const bitIndex = 7 - (x & 7)\n return ((src[byteIndex] >> bitIndex) & 1) as 0|1\n }\n\n const setBit = (x: number, y: number, value: 0|1) => {\n if (x < 0 || y < 0 || x >= widthBits || y >= height) return\n const byteIndex = (y * widthBytes) + (x >> 3)\n const mask = 1 << (7 - (x & 7))\n if (value === 1) dst[byteIndex] |= mask\n else dst[byteIndex] &= (~mask) & 0xff\n }\n\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < widthBits; x++) {\n // We represent black as 0, white as 1.\n const isBlack = (\n getBit(x, y) === 0 ||\n getBit(x - 1, y) === 0 ||\n getBit(x + 1, y) === 0 ||\n getBit(x, y - 1) === 0 ||\n getBit(x, y + 1) === 0 ||\n getBit(x - 1, y - 1) === 0 ||\n getBit(x + 1, y - 1) === 0 ||\n getBit(x - 1, y + 1) === 0 ||\n getBit(x + 1, y + 1) === 0\n )\n setBit(x, y, isBlack ? 0 : 1)\n }\n }\n\n return {\n width: widthBytes,\n height,\n bytes: dst,\n }\n }\n}","import ImageUtils, { BWBitmap } from \"@/helpers/ImageUtils\";\nimport { GraphicMode } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\nimport Device from \"@/helpers/Device\";\n\n/**\n * Represents a bitmap command. Can be used to draw an image to the label\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLBitmapCommand extends TSPLVisualCommand {\n /**\n * Bitmap to present. \n * TSPL only supports black and write printing so this bitmap contains a matrix of 1 (White pixel)\n * and 0 (Black pixel) values\n */\n private readonly bitmap: BWBitmap\n private readonly mode: GraphicMode\n\n /**\n * @param bitmap Bitmap to present. \n * @param x X coordinates in dots\n * @param y Y Coordinates in dots\n * @param mode Represents the strategy to use when two bitmaps overlap. The final value will be determined by\n * either overwriting the first bitmap's value with the second one or performing an 'or' or 'xor' operation on the values\n */\n constructor(bitmap: BWBitmap, x: number, y: number, mode?: GraphicMode) {\n super(x, y);\n this.bitmap = bitmap;\n this.mode = mode ?? \"overwrite\"\n }\n\n get commandString(): string {\n const textDecoder = new TextDecoder('utf-8')\n const bytesString = textDecoder.decode(this.bitmap.bytes)\n\n return `${this.commandWithoutBytes}${bytesString.slice(0,5)}...\\n`;\n }\n\n private get commandWithoutBytes(): string {\n return `BITMAP ${this.x}, ${this.y},${this.bitmap.width},${this.bitmap.height},${this.modeValue},`\n }\n\n private get modeValue(): 0|1|2 {\n switch (this.mode) {\n case \"overwrite\": return 0\n case \"or\": return 1\n case \"xor\": return 2\n }\n }\n\n async writeTo(device: Device): Promise<void> {\n await this.writeString(this.commandWithoutBytes, device)\n await this.writeBytes(this.bitmap.bytes, device)\n await this.terminateCommand(device)\n }\n\n /**\n * Create a new bitmap command for the given image url\n * @param image Image to create command for \n * @param x X coordinate of the image\n * @param y Y coordinate of the image\n * @param imageWidth Desired width of the image\n * @param imageHeight Desired height of the image\n * @param mode Graphics mode\n * @returns \n */\n static async forImageUrl(image: string, x: number, y: number, imageWidth?: number, imageHeight?: number, mode?: GraphicMode) {\n const bitmap = await ImageUtils.getBWBitmap(image, imageWidth, imageHeight)\n return new TSPLBitmapCommand(bitmap, x, y, mode)\n }\n}","export type Rotation = 0|90|180|270\nexport type Alignment = undefined|\"left\"|\"center\"|\"right\"\n\n/**\n * Convert an alignemnt string to its number value\n * @param alignment \n * @returns \n */\nexport const alignmentToNumber = (alignment: Alignment): 0|1|2|3 => {\n switch(alignment) {\n case undefined: return 0\n case \"left\": return 1\n case \"center\": return 2\n case \"right\": return 3\n }\n}\n\n/**\n * Represents the strategy to use when two bitmaps overlap. The final value will be determined by\n * either overwriting the first bitmap's value with the second one or performing an 'or' or 'xor' operation\n * on the values\n */\nexport type GraphicMode = \"overwrite\"|\"or\"|\"xor\"\nexport type LabelDirection = \"normal\"|\"inverse\"\nexport type ECCLevel = \"L\"|\"M\"|\"Q\"|\"H\"\nexport type AutoManual = \"A\"|\"M\"\nexport type QRModel = \"M1\"|\"M2\"\nexport type BarcodeType = \"CODE128\"|\"EAN13\"|\"EAN8\"|\"EAN5\"|\"EAN2\"|\"UPC\"|\"CODE39\"|\"ITF14\"|\"MSI10\"|\"MSI11\"|\"MSI1010\"|\"MSI1110\"|\"pharmacode\"|\"codabar\"\nexport type BarcodeHumanReable = \"none\"|\"left\"|\"right\"|\"center\"","import { Alignment, Rotation, alignmentToNumber } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Prints a single line text on the label\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLTextCommand extends TSPLVisualCommand {\n /**\n * Name of the font to use. Consult documentation for more info\n */\n protected readonly font: string\n /**\n * Angle of rotation of the text. 0, 90, 180 or 270\n */\n protected readonly rotatation: Rotation\n /**\n * Multiplication of the font size in x axis\n */\n protected readonly xMultiplication: number\n /**\n * Multiplication of the font size in y axis\n */\n protected readonly yMultiplication: number\n /**\n * Text alignment. Left, Center or Right. The default alignmnet is left\n */\n protected readonly alignment: number\n /**\n * Text to print\n */\n protected readonly content: string\n\n constructor(content: string, x: number, y: number, font: string, rotation?: Rotation, xMultiplication?: number, yMultiplication?: number, alignment?: Alignment) {\n super(x, y)\n this.font = font\n this.rotatation = rotation ?? 0\n this.xMultiplication = xMultiplication ?? 1\n this.yMultiplication = yMultiplication ?? 1\n this.alignment = alignmentToNumber(alignment)\n this.content = content\n }\n\n get commandString(): string {\n return `TEXT ${this.x},${this.y},\\\"${this.font}\\\",${this.rotatation},${this.xMultiplication},${this.yMultiplication},${this.alignment},\\\"${this.content}\\\"`\n }\n}","import { valueWithUnit } from \"@/helpers/UnitUtils\";\nimport TSPLCommand from \"../../TSPLCommand\";\nimport { UnitSystem } from \"@/commands\";\n\n/**\n * Defines the gap between two labels\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLGapCommand extends TSPLCommand {\n private readonly gap: number\n private readonly offset: number\n\n /**\n * This controls what unit the {@link width} and {@link height} will be\n * - For imperial, the unit is inches\n * - For metric, the unit is milimeters\n * - For dots, the unit is dots\n */\n private readonly unitSystem: UnitSystem\n\n constructor(gap: number, offset: number, unitSystem: UnitSystem) {\n super()\n this.gap = gap\n this.offset = offset\n this.unitSystem = unitSystem\n } \n\n get commandString(): string {\n return `GAP ${valueWithUnit(this.gap, this.unitSystem)}, ${valueWithUnit(this.offset, this.unitSystem)}`\n }\n}","import { valueWithUnit } from \"@/helpers/UnitUtils\";\nimport TSPLCommand from \"../../TSPLCommand\";\nimport { UnitSystem } from \"@/commands\";\n\n/**\n * Defines the size of the label to rpint\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLSizeCommand extends TSPLCommand {\n private readonly width: number\n private readonly height: number\n /**\n * This controls what unit the {@link width} and {@link height} will be\n * - For imperial, the unit is inches\n * - For metric, the unit is milimeters\n * - For dots, the unit is dots\n */\n private readonly unitSystem: UnitSystem\n\n constructor(width: number, height: number, unitSystem: UnitSystem) {\n super()\n this.width = width\n this.height = height\n this.unitSystem = unitSystem\n } \n\n get commandString(): string {\n return `SIZE ${valueWithUnit(this.width, this.unitSystem)}, ${valueWithUnit(this.height, this.unitSystem)}`\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\n\n/**\n * Clear the image buffer\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLCLSCommand extends TSPLCommand {\n get commandString(): string {\n return \"CLS\"\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\nimport { LabelDirection } from \"../../types\";\n\n/**\n * This command defines in which direction will the label be printed and wether or not to mirror the image\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLDirectionCommand extends TSPLCommand {\n private readonly direction: 0|1\n private readonly mirror: 0|1\n\n /**\n * @param direction Controls the orientation of the resulting label compared to the printer\n * @param mirror Controls mirroring relative to the center line of the label perpendicular to the printhead. See the documentsion for examples\n */\n constructor(direction: LabelDirection, mirror?: boolean) {\n super()\n this.direction = direction == \"normal\" ? 1 : 0\n this.mirror = mirror ? 1 : 0\n }\n\n get commandString(): string {\n return `DIRECTION ${this.direction}, ${this.mirror}`\n }\n}\n","import TSPLCommand from \"../../TSPLCommand\";\n\n/**\n * Prints the current image buffer\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLPrintCommand extends TSPLCommand {\n /**\n * The number of set to print.\n */\n private readonly sets: number\n /**\n * The number of copies to print of each set.\n * The difference between a set and a copy is that if you have a counter for example,\n * the counter will be incremented for each set but not for each copy\n */\n private readonly copies: number\n\n constructor(sets: number, copies: number = 1) {\n super()\n this.sets = sets\n this.copies = copies\n }\n\n get commandString(): string {\n return `PRINT ${this.sets}, ${this.copies}`\n }\n}","import TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Draws a black bar\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLBarCommand extends TSPLVisualCommand {\n private readonly width: number\n private readonly height: number\n\n /**\n * @param x X coordinates in dots\n * @param y Y coordinates in dots\n * @param width Width of tha bar in dots\n * @param height Height of the bar in dots\n */\n constructor(x: number, y: number, width: number, height: number) {\n super(x,y)\n this.width = width\n this.height = height\n }\n\n get commandString(): string {\n return `BAR ${this.x}, ${this.y}, ${this.width}, ${this.height}`\n }\n}","import { ECCLevel, AutoManual, Rotation, QRModel } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Prints a QR code\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLQRCommand extends TSPLVisualCommand {\n private readonly ecc: ECCLevel\n private readonly cellWidth: number\n private readonly mode: AutoManual\n private readonly rotation: Rotation\n private readonly model: QRModel\n /**\n * Should be between 0 and 7\n */\n private readonly mask: number\n private readonly content: string\n\n constructor(content: string, \n x: number, \n y: number, \n cellWidth: number, \n ecc: ECCLevel = \"H\", \n mode: AutoManual = \"A\", \n rotation: Rotation = 0, \n model: QRModel = \"M2\", \n mask: number = 7) {\n super(x,y)\n this.content = content\n this.cellWidth = cellWidth\n this.ecc = ecc\n this.mode = mode\n this.rotation = rotation\n this.model = model\n this.mask = mask\n\n if (mask < 0 || mask > 8) {\n throw new Error(`Invalid mask provided: ${mask}`)\n }\n }\n\n get commandString(): string {\n return `QRCODE ${this.x}, ${this.y}, ${this.ecc}, ${this.cellWidth}, ${this.mode}, ${this.rotation}, ${this.model}, \\\"${this.content}\\\"`\n }\n}","import { Alignment, Rotation } from \"../../types\";\nimport TSPLTextCommand from \"./TSPLTextCommand\";\n\nexport default class TSPLBlockCommand extends TSPLTextCommand {\n private readonly width: number\n private readonly height: number\n private readonly lineSpacing: number\n\n constructor(content: string, \n x: number, \n y: number, \n width: number,\n height: number,\n font: string, \n rotation?: Rotation, \n xMultiplication?: number, \n yMultiplication?: number, \n lineSpacing: number = 0,\n alignment?: Alignment) {\n super(content, x, y, font, rotation, xMultiplication, yMultiplication, alignment)\n this.width = width\n this.height = height\n this.lineSpacing = lineSpacing\n }\n\n get commandString(): string {\n return `BLOCK ${this.x},${this.y},${this.width}, ${this.height},\\\"${this.font}\\\",${this.rotatation},${this.xMultiplication},${this.yMultiplication},${this.lineSpacing},${this.alignment},\\\"${this.content}\\\"`\n }\n}","import Device from \"@/helpers/Device\"\nimport TSPLCommand from \"../../TSPLCommand\"\n\ntype Data = ArrayBuffer|Uint8Array\n/**\n * A raw TSPL command. Can be used to use a command that is not yet supported\n */\nexport default class TSPLDownload extends TSPLCommand {\n /**\n * Name of the file on the printer\n */\n private readonly fileName: string\n private readonly data: Data\n\n /**\n * Initialize a command with a raw body\n * @param body\n */\n constructor(fileName: string, data: Data) {\n super()\n this.fileName = fileName\n this.data = data\n }\n\n get commandString(): string {\n return `DOWNLOAD \"${this.fileName}\", ${this.data.byteLength},`\n }\n\n async writeTo(device: Device): Promise<void> {\n await this.writeString(this.commandString, device)\n await this.writeBytes(this.data, device)\n await this.terminateCommand(device)\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\n\nexport type DisplayType = \"CLS\"|\"IMAGE\"|\"OFF\"\n\n/**\n * Displays the image buffer on the screen\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLDisplay extends TSPLCommand {\n private readonly type: DisplayType\n\n constructor(type: DisplayType) {\n super()\n this.type = type\n }\n\n get commandString(): string {\n return `DISPLAY ${this.type}`\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\nimport { Point } from \"@/commands\";\n\nexport default class TSPLDiagonal extends TSPLCommand {\n private readonly start: Point\n private readonly end: Point\n private readonly thickness: number\n\n constructor(start: Point, end: Point, thickness: number = 3) {\n super()\n this.start = start\n this.end = end\n this.thickness = thickness\n }\n\n get commandString(): string {\n return `DIAGONAL ${this.start.x}, ${this.start.y}, ${this.end.x}, ${this.end.y}, ${this.thickness}`\n }\n}","import { Alignment, BarcodeHumanReable, BarcodeType, Rotation, alignmentToNumber } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\n\nexport default class TSPLBarcodeCommand extends TSPLVisualCommand {\n private readonly type: BarcodeType\n private readonly height: number\n private readonly rotation: Rotation\n private readonly humanReadable: number\n private readonly narrow: number\n private readonly wide: number\n private readonly alignment: number\n private readonly content: string\n\n /**\n * @param x X coordinate in dots\n * @param y Y Coordinate in dots\n * @param type Type of the barcode\n * @param height Height of the barcode in dots\n * @param narrow Width of narrow elements in dots\n * @param wide Width of the wide elements in dots\n * @param content Content of the barcode. Supported content depends on the barcode type\n * @param rotation Rotation \n * @param alignment Alignment of the barcode\n */\n constructor(x: number, \n y: number, \n type: BarcodeType, \n height: number, \n narrow: number, \n wide: number,\n content: string,\n rotation: Rotation = 0, \n humanReadable: BarcodeHumanReable = \"left\",\n alignment: Alignment = \"left\") {\n super(x,y)\n this.type = type\n this.height = height\n this.narrow = narrow\n this.wide = wide\n this.content = content\n this.rotation = rotation\n this.humanReadable = TSPLBarcodeCommand.humanReadableValue(humanReadable)\n this.alignment = alignmentToNumber(alignment)\n }\n \n get commandString(): string {\n return `BARCODE ${this.x}, ${this.y}, \\\"${this.type}\\\", ${this.height}, ${this.humanReadable},${this.rotation}, ${this.narrow}, ${this.wide},${this.alignment}, \\\"${this.content}\\\"`\n }\n\n private static humanReadableValue(hr: BarcodeHumanReable): number {\n switch (hr) {\n case \"none\": return 0\n case \"left\": return 1\n case \"center\": return 2\n case \"right\": return 3\n }\n }\n}","// These mappings are for hight error correction level and for alpahnumeric data\n// The mapping has to be interpreted like this: up to (including) 10 characters, we have 21 cells\nexport const QRLengthMapping = {\n 10: 21,\n 20: 25,\n 35: 29,\n 50: 33,\n 64: 37,\n 84: 41,\n 93: 45,\n 122: 49,\n 143: 53,\n 174: 57,\n 200: 61,\n 227: 65,\n 259: 69,\n 283: 73,\n 321: 77,\n 365: 81,\n 408: 85,\n 452: 89,\n 493: 93,\n 557: 97,\n 587: 101,\n 640: 105,\n 672: 109,\n 744: 113,\n 779: 117,\n 864: 121,\n 910: 125,\n 958: 129,\n 1016: 133,\n 1080: 137,\n 1150: 141,\n 1226: 145,\n 1307: 149,\n 1394: 153,\n 1431: 157,\n 1530: 161,\n 1591: 165,\n 1658: 169,\n 1774: 173,\n 1852: 177\n}","import { BitmapLike } from \"@/helpers/ImageUtils\";\nimport { Point, UnitSystem } from \"..\";\nimport CommandGenerator from \"../CommandGenerator\";\nimport TSPLCommand from \"./TSPLCommand\";\nimport { TSPLBitmapCommand, TSPLCLSCommand, TSPLCommandGroup, TSPLDiagonal, TSPLDirectionCommand, TSPLDisplay, TSPLDownload, TSPLGapCommand, TSPLPrintCommand, TSPLQRCommand, TSPLRawCommand, TSPLSizeCommand, TSPLTextCommand } from \"./commands\";\nimport { Alignment, BarcodeHumanReable, BarcodeType, GraphicMode, LabelDirection, Rotation } from \"./types\";\nimport TSPLBarcodeCommand from \"./commands/basic/TSPLBarcodeCommand\";\nimport { QRLengthMapping } from \"@/helpers/QRCodeUtils\";\n\n/**\n * Command generator for tspl commands\n */\nclass TSPLCommandGenerator implements CommandGenerator<TSPLCommand> {\n commandGroup(commands: TSPLCommand[]) {\n return new TSPLCommandGroup(commands)\n }\n\n print(sets: number, copiesPerSet: number): TSPLCommand {\n return new TSPLPrintCommand(sets, copiesPerSet)\n }\n\n text(content: string, x: number, y: number, font: string|\"default\", size: number): TSPLCommand {\n const fontName = font == \"default\" ? \"0\" : font\n return new TSPLTextCommand(content, x, y, fontName, 0, size, size, \"left\")\n }\n\n upload(name: string, data: ArrayBuffer | Uint8Array): TSPLCommand {\n return new TSPLDownload(name, data)\n }\n\n setUp(width: number, height: number, gap: number, offset: number, direction: LabelDirection, mirror: boolean = false, unitSystem: UnitSystem): TSPLCommand {\n const commands = [\n new TSPLSizeCommand(width, height, unitSystem),\n new TSPLGapCommand(gap, offset, unitSystem),\n new TSPLDirectionCommand(direction, mirror),\n new TSPLCLSCommand()\n ]\n\n return new TSPLCommandGroup(commands)\n }\n\n display() {\n return new TSPLCommandGroup([\n new TSPLDisplay(\"CLS\"),\n new TSPLDisplay(\"IMAGE\")\n ])\n }\n\n line(start: Point, end: Point, thickness: number): TSPLCommand {\n return new TSPLDiagonal(start, end, thickness)\n }\n \n image(image: BitmapLike, x: number, y: number, mode?: GraphicMode | undefined): TSPLCommand {\n return new TSPLBitmapCommand(image, x, y, mode)\n }\n\n qrCode(content: string, width: number, x: number, y: number): TSPLCommand {\n const cellCount = this.cellCount(content)\n const cellWidth = Math.round(width / cellCount)\n // We start the content With A to indicate that our data is alphanumeric. \n // Not using auto ensures that we can easily calculate the cell with for a given content\n return new TSPLQRCommand(`A${content}`, x, y, cellWidth, 'H', \"M\")\n }\n \n barCode(content: string, x: number, y: number, type: BarcodeType, height: number, rotation: Rotation, humanReadable: BarcodeHumanReable, alignment: Alignment): TSPLCommand {\n return new TSPLBarcodeCommand(x, y, type, height, 1, 1, content, rotation, humanReadable, alignment)\n }\n\n private cellCount(content: string): number {\n const limits = Object.keys(QRLengthMapping).map( limit => Number(limit) ).sort((a, b) => a - b)\n const contentLength = content.length\n\n let i = 0\n while(limits[i] < contentLength && i < limits.length - 1) {\n i ++\n }\n\n return QRLengthMapping[limits[i] as keyof typeof QRLengthMapping]\n }\n}\n\nexport default new TSPLCommandGenerator()","export { default as Printer } from \"./Printer\"\nexport type { PrinterStatus } from \"./Printer\"\nexport { PrinterService } from \"./PrinterService\"","import { Command, PrinterLanguage } from \"@/commands\";\nimport { LabelDirection } from \"@/commands/tspl\";\nimport Device from \"@/helpers/Device\";\nimport { Label } from \"@/labels\"\n\nexport type PrinterStatus =\n | \"normal\"\n | \"head_opened\"\n | \"paper_jam\"\n | \"paper_jam_head_opened\"\n | \"out_of_paper\"\n | \"out_of_paper_head_opened\"\n | \"out_of_ribbon\"\n | \"out_of_ribbon_head_opened\"\n | \"out_of_ribbon_paper_jam\"\n | \"out_of_ribbon_paper_jam_head_opened\"\n | \"out_of_ribbon_out_of_paper\"\n | \"out_of_ribbon_out_of_paper_head_opened\"\n | \"paused\"\n | \"printing\"\n | \"other_error\"\n\n/**\n * Base class that encapsulates functionality of all printers\n */\nexport default abstract class Printer {\n protected readonly device: Device\n\n /**\n * Printer language used by the type of printer the subclass represents\n */\n abstract get language(): PrinterLanguage\n\n /**\n * When called, it will feed the labels to the beginig of the next label\n */\n abstract feedLabel(): Promise<void>\n\n abstract getModelname(): Promise<string>\n\n abstract getStatus(): Promise<PrinterStatus>\n\n constructor(device: Device) {\n this.device = device\n }\n\n /**\n * Close the printer USB\n */\n async close() {\n await this.device.close()\n }\n\n /**\n * Prints a label\n * @param label \n */\n async print(label: Label, \n sets: number,\n gap: number, \n copiesPerSet: number = 1,\n direction: LabelDirection = \"normal\",\n mirror: boolean = false, \n gapOffset: number = 0) {\n const commands = await label.fullPrintCommand(this.language, gap, direction, sets, copiesPerSet, mirror, gapOffset)\n await this.writeCommand(commands)\n }\n\n /**\n * Display label on the printer's screen\n * @param label \n */\n async display(label: Label, direction: LabelDirection = \"normal\", mirror: boolean = false) {\n const command = await label.fullDisplayCommand(this.language, direction, mirror)\n await this.writeCommand(command)\n }\n\n /**\n * Writes a command to the printers usb\n * @param command Command to send to the usb\n */\n async writeCommand(command: Command): Promise<void> {\n if(!this.device.opened) await this.device.openAndConfigure()\n await command.writeTo(this.device)\n }\n\n /**\n * Writes a raw string to the printer\n * @param text String to send to the printer\n */\n async writeRawString(text: string): Promise<void> {\n if(!this.device.opened) await this.device.openAndConfigure()\n await this.device.writeString(text)\n }\n\n /**\n * Check if the device is indeed a printer\n * @param device \n */\n static try(_device: Device): Promise<boolean> {\n throw new Error(\"try(device:) should be implemented\")\n }\n}","/**\n * Collection of helpers to work with strings\n */\nexport default class StringUtils {\n /**\n * Convert string to utf8 array\n * @param str Convert string to byte array\n */\n toUTF8Array(str: string) {\n let utf8Encode = new TextEncoder();\n return utf8Encode.encode(str)\n }\n\n /**\n * Convert bytes to utf8 encoded string\n * @param bytes Bytes to decode\n * @returns A string\n */\n toString(bytes: Uint8Array|DataView) {\n let decoder = new TextDecoder()\n return decoder.decode(bytes)\n }\n}\n\nexport const isWhitespace = (text: string) => text.trim() === \"\"","import StringUtils from \"./StringUtils\";\n\nconst unsupportedUsbError = \"usb-unsupported\"\nconst stringHelper = new StringUtils()\n\n export type UsbRequestFilter = {\n vendorId?: number\n productId?: number\n }\n\nlet usbAgent: USB\n\n/**\n * @returns The appropiate USB agent based on the environment\n */\nconst getUSB = async (): Promise<USB> => {\n if(usbAgent) return usbAgent\n\n if(typeof window !== \"undefined\") {\n if(navigator.usb) {\n usbAgent = navigator.usb\n } else {\n throw unsupportedUsbError\n }\n } else {\n // TODO: Check how to avoid eval\n const { WebUSB } = eval(\"require\")(\"usb\")\n usbAgent = new WebUSB({allowAllDevices: true})\n }\n\n return usbAgent\n}\n\n/**\n * Returns the list of available devices\n * In node this returns all the connected devices but in the browser it will only return devices \n * that the user already gave permission to\n * @returns A list of available devices\n */\nexport const getDevices = async (): Promise<UsbDevice[]> => {\n const agent = await getUSB()\n const devices = await agent.getDevices()\n return devices.map(device => new UsbDevice(device) )\n}\n\n/**\n * In node, it returns the first available device, in the browser (supported browsers only) it shows \n * a UI for the user to choose a device\n * @returns The first available device\n */\nexport const requestDevice = async (): Promise<UsbDevice|undefined> => {\n const agent = await getUSB()\n const device = await agent.requestDevice({filters: []})\n if(device) {\n return new UsbDevice(device)\n } else {\n return undefined\n }\n}\n\n /**\n * Request a USB device using WebUSB filters.\n *\n * - **Browser**: shows a device picker UI filtered by the supplied `vendorId`/`productId`.\n * - **Node.js**: uses the underlying WebUSB implementation provided by the `usb` package.\n *\n * Note: WebUSB filters support `vendorId` and `productId`. Serial filtering is not\n * part of the WebUSB request filters.\n */\n export const requestDeviceWithFilters = async (filters: UsbRequestFilter[] = []): Promise<UsbDevice|undefined> => {\n const agent = await getUSB()\n const device = await agent.requestDevice({ filters: filters as any })\n if(device) {\n return new UsbDevice(device)\n } else {\n return undefined\n }\n }\n\n/**\n * Convenience wrapper for a web usb device\n * Its main purpose is to hide the details of the usb library from client code so in case\n * it needs to be switched, compatibility can be retained\n */\nexport class UsbDevice {\n private readonly device: USBDevice\n\n get opened() {\n return this.device.opened\n }\n\n get vendorId(): number {\n return this.device.vendorId\n }\n\n get productId(): number {\n return this.device.productId\n }\n\n get serialNumber(): string|undefined {\n return this.device.serialNumber\n }\n\n /**\n * All available endpoints\n */\n private get endpoints() {\n return this.device.configuration?.interfaces[0].alternate.endpoints ?? []\n }\n\n /**\n * Endpoint for writing\n */\n private get outEndpoint() {\n return this.endpoints.find(e => e.direction == \"out\")?.endpointNumber\n }\n\n private get outEndpointPacketSize(): number|undefined {\n return this.endpoints.find(e => e.direction == \"out\")?.packetSize\n }\n\n /**\n * Endpoint for reading\n */\n private get inEndpoint() {\n return this.endpoints.find(e => e.direction == \"in\")?.endpointNumber\n }\n\n constructor(device: USBDevice) {\n this.device = device\n }\n\n /**\n * Open the device and claim its interface\n */\n async openAndConfigure() {\n await this.device.open();\n await this.device.selectConfiguration(1);\n await this.device.claimInterface(0);\n }\n\n /**\n * Closes the device\n */\n async close() {\n await this.device.releaseInterface(0)\n await this.device.close()\n }\n\n /**\n * Write data to an USB device\n * @param data Data to write\n */\n async writeData(data: Uint8Array|ArrayBuffer): Promise<void> {\n const endpointNumber = this.outEndpoint\n if(endpointNumber == null) {\n throw new Error(\"usb-no-out-endpoint\")\n }\n await this.device.transferOut(endpointNumber, data as BufferSource)\n }\n\n /**\n * Writes a text to a device\n * @param text Text to write\n */\n async writeString(text: string): Promise<void> {\n const bytes = stringHelper.toUTF8Array(text)\n await this.writeData(bytes)\n }\n\n /**\n * Reads bytes from the usb device\n * @param length The max length of the incoming data. \n * @returns Bytes received as a DataView or undefined. If data is longer then `length`, undefined will be returned\n */\n async readData(length: number): Promise<DataView|undefined> {\n const endpointNumber = this.inEndpoint\n if(endpointNumber == null) {\n throw new Error(\"usb-no-in-endpoint\")\n }\n const result = await this.device.transferIn(endpointNumber, length)\n\n if(result.status == \"ok\" && result.data) {\n return result.data\n } else {\n return undefined\n }\n }\n\n /**\n * Reads data from the usb device and converts it to string\n * {@see readData}\n */\n async readString(length: number): Promise<string|undefined> {\n const bytes = await this.readData(length)\n if(bytes) return stringHelper.toString(bytes)\n return undefined\n }\n}\n","import StringUtils from \"./StringUtils\";\nimport type Device from \"./Device\";\n\nconst unsupportedNetworkError = \"network-unsupported\"\nconst stringHelper = new StringUtils()\n\ntype NetSocket = {\n write(data: Uint8Array|ArrayBuffer|string, cb?: (err?: Error) => void): boolean\n end(): void\n destroy(): void\n on(event: \"data\", listener: (data: Buffer) => void): any\n on(event: \"error\", listener: (err: Error) => void): any\n once(event: \"data\", listener: (data: Buffer) => void): any\n once(event: \"error\", listener: (err: Error) => void): any\n removeListener(event: \"data\"|\"error\", listener: (...args: any[]) => void): any\n}\n\ntype NetModule = {\n createConnection(options: { host: string, port: number }, listener?: () => void): NetSocket\n}\n\nconst getNet = (): NetModule => {\n if(typeof window !== \"undefined\") {\n throw unsupportedNetworkError\n }\n\n // TODO: Check how to avoid eval\n return eval(\"require\")(\"net\") as NetModule\n}\n\nexport default class NetworkDevice implements Device {\n private socket?: NetSocket\n private readonly host: string\n private readonly port: number\n private readonly connectTimeoutMs: number\n private readonly readTimeoutMs: number\n\n /**\n * Create a TCP-based device.\n *\n * This is intended for raw printing ports (typically 9100). It is Node-only.\n *\n * @param host Hostname or IP\n * @param port TCP port (defaults to 9100)\n * @param connectTimeoutMs Connection timeout\n * @param readTimeoutMs Read timeout used by `readData`/`readString`\n */\n constructor(host: string, port: number = 9100, connectTimeoutMs: number = 2000, readTimeoutMs: number = 500) {\n this.host = host\n this.port = port\n this.connectTimeoutMs = connectTimeoutMs\n this.readTimeoutMs = readTimeoutMs\n }\n\n get opened(): boolean {\n return !!this.socket\n }\n\n async openAndConfigure(): Promise<void> {\n if(this.socket) return\n\n const net = getNet()\n\n await new Promise<void>((resolve, reject) => {\n let settled = false\n const timeout = setTimeout(() => {\n if(settled) return\n settled = true\n try { this.socket?.destroy() } catch (_e) {}\n this.socket = undefined\n reject(new Error(\"network-connect-timeout\"))\n }, this.connectTimeoutMs)\n\n try {\n const socket = net.createConnection({ host: this.host, port: this.port }, () => {\n if(settled) return\n settled = true\n clearTimeout(timeout)\n resolve()\n })\n\n socket.once(\"error\", (err) => {\n if(settled) return\n settled = true\n clearTimeout(timeout)\n this.socket = undefined\n reject(err)\n })\n\n this.socket = socket\n } catch (e) {\n if(settled) return\n settled = true\n clearTimeout(timeout)\n this.socket = undefined\n reject(e)\n }\n })\n }\n\n async close(): Promise<void> {\n if(!this.socket) return\n const socket = this.socket\n this.socket = undefined\n\n try {\n socket.end()\n } catch (_e) {\n try { socket.destroy() } catch (_e2) {}\n }\n }\n\n async writeData(data: Uint8Array|ArrayBuffer): Promise<void> {\n if(!this.socket) {\n throw new Error(\"network-not-open\")\n }\n\n await new Promise<void>((resolve, reject) => {\n try {\n this.socket!.write(data as any, (err?: Error) => {\n if(err) reject(err)\n else resolve()\n })\n } catch (e) {\n reject(e)\n }\n })\n }\n\n async writeString(text: string): Promise<void> {\n const bytes = stringHelper.toUTF8Array(text)\n await this.writeData(bytes)\n }\n\n async readData(length: number): Promise<DataView|undefined> {\n if(!this.socket) {\n throw new Error(\"network-not-open\")\n }\n\n const socket = this.socket\n const buffer = await new Promise<Buffer|undefined>((resolve, reject) => {\n let settled = false\n\n const onData = (data: Buffer) => {\n if(settled) return\n settled = true\n cleanup()\n resolve(data)\n }\n\n const onError = (err: Error) => {\n if(settled) return\n settled = true\n cleanup()\n reject(err)\n }\n\n const cleanup = () => {\n clearTimeout(timeout)\n socket.removeListener(\"data\", onData)\n socket.removeListener(\"error\", onError)\n }\n\n const timeout = setTimeout(() => {\n if(settled) return\n settled = true\n cleanup()\n resolve(undefined)\n }, this.readTimeoutMs)\n\n socket.once(\"data\", onData)\n socket.once(\"error\", onError)\n })\n\n if(!buffer) return undefined\n if(buffer.byteLength > length) return undefined\n\n return new DataView(buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength))\n }\n\n async readString(length: number): Promise<string|undefined> {\n const bytes = await this.readData(length)\n if(bytes) return stringHelper.toString(bytes)\n return undefined\n }\n}\n","const unsupportedBonjourError = \"bonjour-unsupported\"\n\ntype BonjourBrowser = {\n stop(): void\n on(event: \"up\", listener: (service: any) => void): any\n}\n\ntype BonjourInstance = {\n find(options: { type: string }, cb?: (service: any) => void): BonjourBrowser\n destroy(): void\n}\n\nconst getBonjour = (): (() => BonjourInstance) => {\n if(typeof window !== \"undefined\") {\n throw unsupportedBonjourError\n }\n\n // TODO: Check how to avoid eval\n const mod: any = eval(\"require\")(\"bonjour\")\n const factory: any = (mod && (mod.default ?? mod))\n if(typeof factory !== \"function\") {\n throw new Error(\"bonjour-invalid-module\")\n }\n return factory as () => BonjourInstance\n}\n\nexport type BonjourService = {\n host: string\n port: number\n name?: string\n type?: string\n}\n\n/**\n * Discover services using Bonjour/mDNS.\n *\n * This is a Node-only helper. It dynamically requires the `bonjour` module so the library can\n * still be imported/bundled in browser contexts.\n *\n * @param types Bonjour service types without the leading underscore (e.g. `printer`, `ipp`)\n * @param timeoutMs Discovery window\n */\nexport const discoverBonjourServices = async (types: string[], timeoutMs: number = 1500): Promise<BonjourService[]> => {\n if(typeof window !== \"undefined\") return []\n\n const factory = getBonjour()\n const bonjour = factory()\n\n try {\n const results: BonjourService[] = []\n const seen = new Set<string>()\n\n const browsers: BonjourBrowser[] = types.map((type) => {\n return bonjour.find({ type }, (service: any) => {\n const host = service?.referer?.address || service?.host\n const port = service?.port\n if(!host || !port) return\n\n const key = `${host}:${port}`\n if(seen.has(key)) return\n seen.add(key)\n\n results.push({ host, port, name: service?.name, type })\n })\n })\n\n await new Promise<void>((resolve) => setTimeout(resolve, timeoutMs))\n\n for (const browser of browsers) {\n try { browser.stop() } catch (_e) {}\n }\n\n return results\n } finally {\n try { bonjour.destroy() } catch (_e) {}\n }\n}\n","import { TSPLRawCommand } from \"@/commands/tspl\";\nimport { PrinterLanguage } from \"@/commands\"\nimport Printer, { PrinterStatus } from \"./Printer\";\nimport Device from \"@/helpers/Device\";\nimport NetworkDevice from \"@/helpers/NetworkDevice\";\nimport { discoverBonjourServices } from \"@/helpers/BonjourUtils\";\n\nexport default class TSPLPrinter extends Printer {\n get language(): PrinterLanguage {\n return \"tspl\"\n }\n\n async feedLabel(): Promise<void> {\n const feedCommand = new TSPLRawCommand(\"FORMFEED\")\n await this.writeCommand(feedCommand)\n }\n\n async getModelname(): Promise<string> {\n if(!this.device.opened) await this.device.openAndConfigure()\n const command = new TSPLRawCommand(\"~!T\")\n await command.writeTo(this.device)\n\n const response = await this.device.readString(256)\n return (response ?? \"\").trim()\n }\n\n async getStatus(): Promise<PrinterStatus> {\n if(!this.device.opened) await this.device.openAndConfigure()\n\n await this.device.writeData(new Uint8Array([0x1b, 0x21, 0x3f, 0x0a]))\n\n const data = await this.device.readData(1)\n const raw = data ? data.getUint8(0) : 0x80\n\n return TSPLPrinter.statusFor(raw)\n }\n\n private static statusFor(code: number): PrinterStatus {\n const map: Record<number, PrinterStatus> = {\n 0x00: \"normal\",\n 0x01: \"head_opened\",\n 0x02: \"paper_jam\",\n 0x03: \"paper_jam_head_opened\",\n 0x04: \"out_of_paper\",\n 0x05: \"out_of_paper_head_opened\",\n 0x08: \"out_of_ribbon\",\n 0x09: \"out_of_ribbon_head_opened\",\n 0x0A: \"out_of_ribbon_paper_jam\",\n 0x0B: \"out_of_ribbon_paper_jam_head_opened\",\n 0x0C: \"out_of_ribbon_out_of_paper\",\n 0x0D: \"out_of_ribbon_out_of_paper_head_opened\",\n 0x10: \"paused\",\n 0x20: \"printing\",\n 0x80: \"other_error\",\n }\n\n return map[code] ?? \"other_error\"\n }\n\n static async try(device: Device): Promise<boolean> {\n if(!device.opened) await device.openAndConfigure()\n const testCommand = new TSPLRawCommand(\"~!I\")\n await testCommand.writeTo(device)\n\n const response = await device.readString(64)\n await device.close()\n // If there is a response, we have a TSPL printer\n return !!response\n }\n\n /**\n * Discover TSPL-capable printers on the local network.\n *\n * Strategy:\n * - Use Bonjour/mDNS to discover \"printer-ish\" services to obtain a set of candidate hosts.\n * - For each unique host, probe TCP/9100 by sending the TSPL identify command (~!I).\n * - Only return devices that respond to the TSPL probe.\n * - If Bonjour yields no candidates (e.g. mDNS is blocked), fall back to a conservative\n * subnet scan on local private /24 networks (still verified by the same TSPL probe).\n */\n static async discoverDevices(): Promise<NetworkDevice[]> {\n if(typeof window !== \"undefined\") return []\n\n const services = await discoverBonjourServices([\n \"pdl-datastream\",\n \"printer\",\n \"ipp\",\n \"ipps\",\n ])\n\n let uniqueHosts = Array.from(new Set(services.map(s => s.host).filter(Boolean)))\n\n if(uniqueHosts.length === 0) {\n uniqueHosts = await TSPLPrinter.discoverHostsBySubnetScan()\n }\n\n const candidates = uniqueHosts.map(host => ({ host, port: 9100 }))\n\n const concurrency = 5\n const verified: NetworkDevice[] = []\n\n for (let i = 0; i < candidates.length; i += concurrency) {\n const batch = candidates.slice(i, i + concurrency)\n\n const results = await Promise.all(batch.map(async (c) => {\n const device = new NetworkDevice(c.host, c.port, 4000, 1000)\n try {\n const ok = await TSPLPrinter.try(device)\n return ok ? device : undefined\n } catch (_e) {\n try { await device.close() } catch (_e2) {}\n return undefined\n }\n }))\n\n verified.push(...(results.filter(Boolean) as NetworkDevice[]))\n }\n\n return verified\n }\n\n /**\n * Fallback discovery mechanism used when Bonjour/mDNS returns no printer candidates.\n *\n * It derives local private IPv4 /24 prefixes from the current machine's network interfaces\n * and probes TCP/9100 using the TSPL identify command.\n *\n * The scan is intentionally conservative:\n * - Limited number of prefixes\n * - Concurrency limits\n * - Total time cap\n * - Early-exit when at least one printer is found\n */\n private static async discoverHostsBySubnetScan(): Promise<string[]> {\n if(typeof window !== \"undefined\") return []\n\n const req = TSPLPrinter.getNodeRequire()\n if(!req) return []\n\n const os: any = req(\"os\")\n const networkInterfaces: any = os.networkInterfaces?.() ?? {}\n\n const privatePrefixes = new Set<string>()\n\n const isPrivateIpv4 = (ip: string): boolean => {\n if(ip.startsWith(\"10.\")) return true\n if(ip.startsWith(\"192.168.\")) return true\n const m = ip.match(/^172\\.(\\d+)\\./)\n if(m) {\n const n = Number(m[1])\n return n >= 16 && n <= 31\n }\n return false\n }\n\n for (const key of Object.keys(networkInterfaces)) {\n const infos = networkInterfaces[key] ?? []\n for (const info of infos) {\n const family = info?.family\n const address = info?.address\n const internal = info?.internal\n if(internal) continue\n if(family !== \"IPv4\") continue\n if(typeof address !== \"string\") continue\n if(!isPrivateIpv4(address)) continue\n\n const parts = address.split(\".\")\n if(parts.length !== 4) continue\n privatePrefixes.add(`${parts[0]}.${parts[1]}.${parts[2]}`)\n }\n }\n\n const prefixes = Array.from(privatePrefixes).slice(0, 2)\n if(prefixes.length === 0) return []\n\n const hosts: string[] = []\n for (const prefix of prefixes) {\n for (let i = 1; i <= 254; i++) {\n hosts.push(`${prefix}.${i}`)\n }\n }\n\n const concurrency = 30\n const verifiedHosts: string[] = []\n const startedAt = Date.now()\n const maxDurationMs = 15000\n\n for (let i = 0; i < hosts.length; i += concurrency) {\n if(Date.now() - startedAt > maxDurationMs) break\n if(verifiedHosts.length > 0) break\n const batch = hosts.slice(i, i + concurrency)\n const results = await Promise.all(batch.map(async (host) => {\n const device = new NetworkDevice(host, 9100, 800, 800)\n try {\n const ok = await TSPLPrinter.try(device)\n return ok ? host : undefined\n } catch (_e) {\n try { await device.close() } catch (_e2) {}\n return undefined\n }\n }))\n\n verifiedHosts.push(...(results.filter(Boolean) as string[]))\n }\n\n return verifiedHosts\n }\n\n /**\n * Returns a Node-style `require` function.\n *\n * This is used to keep runtime dependencies Node-only while still allowing the library to\n * be imported/bundled in browser contexts.\n *\n * Tests may inject a custom require implementation via `globalThis.__label_printer_require`.\n */\n private static getNodeRequire(): ((module: string) => any) | undefined {\n if(typeof window !== \"undefined\") return undefined\n\n const override = (globalThis as any).__label_printer_require\n if(typeof override === \"function\") return override\n\n // TODO: Check how to avoid eval\n return eval(\"require\")\n }\n}","import Device from \"@/helpers/Device\"\nimport { getDevices, requestDevice, requestDeviceWithFilters } from \"@/helpers/USBUtils\"\nimport NetworkDevice from \"@/helpers/NetworkDevice\"\nimport TSPLPrinter from \"./TSPLPrinter\"\nimport Printer from \"./Printer\"\n\nexport type PrinterServiceUsbConnectOptions = {\n vendorId?: number\n productId?: number\n serialNumber?: string\n}\n\nexport type PrinterServiceNetworkConnectOptions = {\n host: string\n port?: number\n}\n\nexport type PrinterServiceConnectOptions =\n | { usb: PrinterServiceUsbConnectOptions }\n | { network: PrinterServiceNetworkConnectOptions }\n\nexport class PrinterService {\n /**\n * Try each type of printer and return the one that mathces the usb device\n * @param device \n * @returns \n */\n static async printerForDevice(device: Device): Promise<Printer|undefined> {\n const classes = [TSPLPrinter]\n\n for (const key in classes) {\n try {\n if(await classes[key].try(device)) {\n return new classes[key](device)\n }\n } catch (_e) {\n return undefined\n }\n }\n\n return undefined\n }\n\n /**\n * Discover devices using printer-specific discovery hooks.\n *\n * Each printer class may optionally implement `static discoverDevices(): Promise<Device[]>`\n * to find candidates over non-USB transports.\n *\n * Candidates returned here are still verified by `printerForDevice` via the printer\n * class' `try(device)` method.\n */\n private static async discoverDevices(): Promise<Device[]> {\n const classes = [TSPLPrinter]\n\n const discoveryResults = await Promise.all(classes.map(async (cls) => {\n const discoverer = (cls as any).discoverDevices\n if(typeof discoverer === \"function\") {\n try {\n return await discoverer.call(cls)\n } catch (_e) {\n return []\n }\n }\n return []\n }))\n\n return discoveryResults.flat()\n }\n\n /**\n * @returns List of available printers\n */\n static async getPrinters(): Promise<Printer[]> {\n const usbDevices = await getDevices()\n const discoveredDevices = await PrinterService.discoverDevices()\n const devices: Device[] = [...usbDevices, ...discoveredDevices]\n\n const optionalPrinters = await Promise.all(devices.map(PrinterService.printerForDevice))\n return optionalPrinters.filter(printer => !!printer) as Printer[]\n }\n\n /**\n * This is intended to be used in the browser although it also works in node\n * In the browser, it provides a UI for the user to choose a USB device and if it is a\n * printer, it returns a new printer instance. In Node however, this will try to create\n * a printer for the first available device and returns it. This means that even if there is a \n * printer, it may return undefined. In node, use `getPrinters` instead\n */\n static async requestPrinter(): Promise<Printer|undefined> {\n const device = await requestDevice()\n if(device) {\n return PrinterService.printerForDevice(device)\n }\n }\n\n /**\n * Create a printer instance using explicit connection information.\n *\n * This is useful when you already know your printer's network address or USB identifiers\n * and want to bypass discovery.\n *\n * Behavior differs by environment:\n * - **Node.js**\n * - `network`: connects via TCP (defaults to port `9100`)\n * - `usb`: selects the first connected USB device matching the provided filters\n * - **Browser**\n * - `usb`: shows the WebUSB picker (optionally filtered by `vendorId`/`productId`)\n * - `network`: not supported (will throw if network transport is used in the browser)\n */\n static async connect(options: PrinterServiceConnectOptions): Promise<Printer|undefined> {\n const device = await PrinterService.deviceForConnectOptions(options)\n if(!device) return undefined\n return PrinterService.printerForDevice(device)\n }\n\n /**\n * Create a TSPL printer instance using explicit connection information.\n *\n * This still verifies the target by probing it with the TSPL identify command (`~!I`).\n * If the probe fails, `undefined` is returned.\n */\n static async connectTSPL(options: PrinterServiceConnectOptions): Promise<TSPLPrinter|undefined> {\n const device = await PrinterService.deviceForConnectOptions(options)\n if(!device) return undefined\n\n const ok = await TSPLPrinter.try(device)\n if(!ok) return undefined\n return new TSPLPrinter(device)\n }\n\n /**\n * Convert user-facing connect options into a concrete device.\n *\n * This keeps transport details (USB vs TCP socket) out of the public API.\n */\n private static async deviceForConnectOptions(options: PrinterServiceConnectOptions): Promise<Device|undefined> {\n if(\"network\" in options) {\n const port = options.network.port ?? 9100\n return new NetworkDevice(options.network.host, port)\n }\n\n const filters = [{ vendorId: options.usb.vendorId, productId: options.usb.productId }].filter(f => f.vendorId != null || f.productId != null)\n\n if(typeof window !== \"undefined\") {\n if(filters.length > 0) return requestDeviceWithFilters(filters as any)\n return requestDevice()\n }\n\n const devices = await getDevices()\n\n const matching = devices.filter(d => {\n if(options.usb.vendorId != null && d.vendorId !== options.usb.vendorId) return false\n if(options.usb.productId != null && d.productId !== options.usb.productId) return false\n if(options.usb.serialNumber != null && d.serialNumber !== options.usb.serialNumber) return false\n return true\n })\n\n return matching[0]\n }\n}","export { default as Label } from \"./Label\"\nexport * from \"./fields\"","import { Command, PrinterLanguage, tspl } from \"@/commands\";\nimport CommandGenerator from \"@/commands/CommandGenerator\";\nimport { Printer } from \"@/printers\";\nimport { FontOption } from \"./types\";\n\nexport type PrintConfig = {\n dpi: number,\n /** Width of the text in dots */\n textWidth: (text: string, font: FontOption) => number,\n getFontName: (font: FontOption) => string\n}\n\n/**\n * A component that can be directly printed to label printer\n */\nexport default abstract class Printable {\n /**\n * Generates a printable command\n * @param language The printing language that should be used\n * @returns A promise of a command that can be printed\n */\n abstract commandForLanguage(language: PrinterLanguage, config?: PrintConfig): Promise<Command>\n\n /**\n * Generates printable command for the given printer. Can be used to obtain a command for fields supported by the package then customizing it before printing\n * @param printer Printer to generate the command. Important because the command is printer language specific\n * @returns A promise for a command. Most commands are syncronouse but some may require to access async resources\n */\n async commandForPrinter(printer: Printer, config?: PrintConfig): Promise<Command> {\n return await this.commandForLanguage(printer.language, config)\n }\n\n /**\n * Obtain a command generator for the given language\n * @param language Language to get generator for\n */\n protected commandGeneratorFor(language: PrinterLanguage): CommandGenerator<any> {\n switch(language) {\n case \"tspl\": return tspl.commandGenerator\n }\n }\n}","import { Command, PrinterLanguage } from \"@/commands\";\nimport Printable, { PrintConfig } from \"./Printable\";\nimport { UnitSystem } from \"@/commands\";\nimport { LabelDirection } from \"@/commands/tspl\";\nimport LabelField from \"./fields/LabelField\";\nimport { Font, FontOption, FontStyle, IndexedFont, IndexedFontFamily } from \"./types\";\nimport CommandGenerator from \"@/commands/CommandGenerator\";\nimport * as fontkit from \"fontkit\"\nimport { dotToPoint, pointsToDots } from \"@/helpers/UnitUtils\";\n\nconst DEFAULT_FONT_WEIGHT = 400\nconst DEFAULT_FONT_STYLE = \"normal\"\nconst FONT_PREFIX = \"f\"\n\n/**\n * Holds the content of a label and handles printing\n */\nexport default class Label extends Printable {\n /**\n * Width of label in dots, mm or inch\n */\n private readonly width: number\n /**\n * Height of label in dots, mm or inch\n */\n private readonly height: number\n\n /**\n * Units for width, height, gap and offset\n */\n private readonly unitSystem: UnitSystem\n private fonts: Record<string, IndexedFontFamily> = {}\n private dpi: number\n\n /**\n * List of fields on the label\n */\n private fields: LabelField[] = []\n private fontCounter = 0\n\n /**\n * Configuration used when generating commands\n */\n get printConfig(): PrintConfig {\n return { \n dpi: this.dpi,\n textWidth: (text, font) => {\n const indexedFont = this.getIndexedFont(font)\n if(indexedFont == null) {\n return text.length * font.size\n } else {\n const size = dotToPoint(font.size, this.dpi)\n const fontObject = indexedFont.font\n \n const run = fontObject.layout(text)\n\n const scaledWidth = size * run.advanceWidth / fontObject.unitsPerEm\n return pointsToDots(scaledWidth, this.dpi)\n }\n },\n getFontName: this.getFontName.bind(this)\n } \n }\n\n constructor(width: number, height: number, dimensionUnit: UnitSystem = \"metric\", dpi: number = 203) {\n super()\n this.width = width\n this.height = height\n this.unitSystem = dimensionUnit\n this.dpi = dpi\n }\n\n async commandForLanguage(language: PrinterLanguage, config?: PrintConfig): Promise<Command> {\n const configuration = config ?? this.printConfig\n const commandList = await Promise.all(this.fields.map(field => field.commandForLanguage(language, configuration)))\n return this.commandGeneratorFor(language).commandGroup(commandList)\n }\n\n /**\n * Place fields to a label\n * @param fields \n */\n add(...fields: LabelField[]) {\n this.fields.push(...fields)\n }\n\n /**\n * Register a font to be used. Use the name provided in components to use the font. \n * For example: textField.setFont('myFont.ttf', 12)\n * @param file Font file. Can be a blob or a url\n * @param name Name to be used to reference the font\n */\n async registerFont(font: Omit<Font, \"font\">) {\n const key = this.fontKey(font.weight, font.style)\n\n if(!this.fonts[font.name]) {\n this.fonts[font.name] = {\n fonts: {}\n }\n }\n\n const fontBuffer = Buffer.from(font.data)\n const builtFont = fontkit.create(fontBuffer)\n // @ts-ignore\n const finalFont = builtFont.fonts ? builtFont.fonts[0] : builtFont\n this.fonts[font.name].fonts[key] = {\n ...font,\n font: finalFont,\n alias: `${FONT_PREFIX}${this.fontCounter}.${this.fontExtension}`\n }\n this.fontCounter += 1\n }\n\n /**\n * Generate a command that is complete for printing\n * @param language Printing language to use\n * @param gap Distance between two labels. It is measured between the two points where the sensor \n * leaves the label and enters the next one\n * @param direction Direction relative to printing direction. See documentation for more details\n * @param sets Number of sets to print. If you have counters for example, it will not change in a set\n * @param copiesPerSet Number of labels per set\n * @param mirror Mirror the label along the vertical axis\n * @param gapOffset Used with non uniform shaped labels. Is the distance between the point where the sensor leaves the label and the \n * furthest point of the label in the direction of printing. Check documentation for more info\n * TODO: Is this too TSPL Specific?\n */\n async fullPrintCommand(language: PrinterLanguage, \n gap: number, \n direction: LabelDirection, \n sets: number, \n copiesPerSet: number = 1,\n mirror: boolean = false, \n gapOffset: number = 0\n ): Promise<Command> {\n\n const generator = this.commandGeneratorFor(language)\n const commands = await this.fullCommand(language, gap, direction, mirror, gapOffset, generator)\n commands.push(generator.print(sets, copiesPerSet))\n\n return generator.commandGroup(commands)\n }\n\n /**\n * Generate commands needed to display the label on the printer screen\n * @param language Printing language to use\n * @param direction Direction relative to printing direction. See documentation for more details\n * @param mirror Mirror the label along the vertical axis\n */\n async fullDisplayCommand(language: PrinterLanguage, direction: LabelDirection, mirror: boolean = false) {\n const generator = this.commandGeneratorFor(language)\n const commands = await this.fullCommand(language, 0, direction, mirror, 0, generator)\n commands.push(generator.display())\n \n return generator.commandGroup(commands)\n }\n\n /**\n * Helper function that generates common commands for print and display\n */\n private async fullCommand(language: PrinterLanguage, \n gap: number, \n direction: LabelDirection, \n mirror: boolean = false, \n gapOffset: number = 0, \n generator: CommandGenerator<any>) {\n const commands = [\n this.fontUploadCommands(generator),\n generator.setUp(this.width, this.height, gap, gapOffset, direction, mirror, this.unitSystem),\n (await this.commandForLanguage(language, this.printConfig)),\n ]\n return commands\n }\n\n private fontUploadCommands(generator: CommandGenerator<any>): Command {\n const families = Object.keys(this.fonts)\n const commands = families.flatMap(family => {\n const familyFonts = this.fonts[family].fonts\n const fontNames = Object.keys(familyFonts)\n\n return fontNames.map(name => {\n const font = familyFonts[name]\n const fileName = font.alias\n\n // @ts-ignore\n return generator.upload(fileName, font.data)\n })\n })\n\n return generator.commandGroup(commands)\n }\n\n private getIndexedFont(font: FontOption): IndexedFont|null {\n const family = this.fonts[font.name]\n if (!family) return null\n \n const style = font.style ?? DEFAULT_FONT_STYLE\n const weigth = font.weight ?? DEFAULT_FONT_WEIGHT\n\n const fontKeys = Object.keys(family.fonts)\n const exactMatch = fontKeys.find(key => \n family.fonts[key].style == style &&\n family.fonts[key].weight == weigth\n )\n\n // If there is a font that matches exactly the requested one we return that\n // otherwise we find the one that is the closest in weight\n // if there is no font with the same style, we return the first normal font in the family\n if(exactMatch) {\n return family.fonts[exactMatch]\n } else {\n const sameStyleKeys = fontKeys.filter(key => family.fonts[key].style == style)\n\n if(sameStyleKeys.length > 0){\n let weigthDiff = 99999999\n let selectedKey = \"\"\n\n sameStyleKeys.forEach(key => {\n const diff = Math.abs(weigth - family.fonts[key].weight)\n if(diff < weigthDiff) {\n weigthDiff = diff\n selectedKey = key\n }\n })\n\n return family.fonts[selectedKey]\n } else {\n return family.fonts[fontKeys[0]]\n }\n }\n }\n\n private getFontName(font: FontOption) {\n // We don't access values directly passed in to make sure the font name we return exists\n const indexedFont = this.getIndexedFont(font)\n if(indexedFont == null) {\n return font.name\n }\n return indexedFont.alias\n // return this.getFontNameForIndexed({name: font.name, weight: indexedFont.weight, style: indexedFont.style})\n }\n\n /// This can be extended when we want support multiple fonts\n private get fontExtension() {\n return \"TTF\"\n }\n\n private fontKey(weight: number, style?: FontStyle) {\n return `${weight}${style ?? DEFAULT_FONT_STYLE}`\n }\n}","import Printable from \"../Printable\";\n\nexport default abstract class LabelField extends Printable {}","import { Command, Point, PrinterLanguage } from \"@/commands\";\nimport LabelField from \"./LabelField\";\n\n/**\n * Draws a line to the screen\n */\nexport default class Line extends LabelField {\n private readonly start: Point\n private readonly end: Point\n private readonly thickness: number\n\n /**\n * \n * @param start Start point of the line. Values are in dots\n * @param end End point of the line. Values are in dots\n * @param thickness Thickness of the line in dots \n */\n constructor(start: Point, end: Point, thickness: number = 3) {\n super()\n this.start = start\n this.end = end\n this.thickness = thickness\n }\n\n commandForLanguage(language: PrinterLanguage): Promise<Command> {\n return this.commandGeneratorFor(language).line(this.start, this.end, this.thickness)\n }\n}","import { Command, PrinterLanguage } from \"@/commands\"\nimport LabelField from \"./LabelField\"\nimport { PrintConfig } from \"../Printable\"\nimport { dotToPoint } from \"@/helpers/UnitUtils\"\nimport CommandGenerator from \"@/commands/CommandGenerator\"\nimport { isWhitespace } from \"@/helpers/StringUtils\"\nimport { NodeType, parse, HTMLElement, Node } from \"node-html-parser\"\nimport { FontOption } from \"../types\"\n\nexport type TextFieldType = \"singleline\"|\"multiline\"\ntype Context = {\n language: PrinterLanguage,\n generator: CommandGenerator<any>,\n config?: PrintConfig\n}\n\ntype TextDecoration = \"underline\"|\"strike\"\n\nconst BOLD_WEIGTH = 700\nconst BOLD_TAG = \"b\"\nconst ITALIC_TAG = \"i\"\nconst UNDERLINE_TAG = \"u\"\nconst STRIKE_TAG = [\"s\", \"del\", \"strike\"]\nconst PARAGRAPH_TAG = \"p\"\nconst BREAK_TAG = \"br\"\n\n/**\n * Presents a piece of text on the label\n */\nexport default class Text extends LabelField {\n private readonly content: string\n /**\n * X coordinate in dots\n */\n private readonly x: number\n /**\n * Y coordinate in dots\n */\n private readonly y: number\n /**\n * If true, basic html elements will be interpretted, otherwise the raw string is printed out\n */\n private readonly formatted: boolean\n private font: FontOption = {name: \"default\", size: 10}\n private type: TextFieldType = \"singleline\"\n private context: Context|undefined = undefined\n private readonly lineSpacing = 1\n\n private endsWithBreak(node: Node): boolean {\n if(node.nodeType == NodeType.TEXT_NODE) {\n return node.innerText.trim() == \"\"\n }\n\n const elementNode = node as HTMLElement\n if(elementNode.rawTagName == BREAK_TAG) return true\n\n const children = elementNode.childNodes\n for(let i = children.length - 1; i >= 0; i--) {\n const child = children[i]\n if(child.nodeType == NodeType.TEXT_NODE) {\n if(child.innerText.trim() == \"\") continue\n return false\n }\n\n if(this.endsWithBreak(child)) return true\n return false\n }\n\n return false\n }\n\n /**\n * Width of the text. \n * If set, the text will be clipped to this size\n * If the type is set to multiline, this is where the text is split to a newline\n */\n private width: number|undefined\n /**\n * Height of the text box, if empty and the type is multiline, the box can grow infinitely\n */\n private height: number|undefined\n \n constructor(content: string, x: number, y: number, formatted: boolean = true) {\n super()\n this.content = content.replace(\"\\n\", \"\").replace(\"\\\"\", \"\\\\\\\"\") // Newline can break text generation\n this.x = x\n this.y = y\n this.formatted = formatted\n }\n\n /**\n * Sets the field to single line\n * @param width Max width of the text. Leave it undefined to allow the field to grow \n */\n setSingleLine(width?: number) {\n this.type = \"singleline\"\n this.width = width\n this.height = undefined\n }\n\n /**\n * Sets the field to multi line\n * @param width Max width of text before it gets wrapped to a new line\n * @param height Max height of the text box, leave undefined to allow the text box to grow infinitly\n */\n setMultiLine(width: number, height?: number) {\n this.type = \"multiline\"\n this.width = width\n this.height = height\n }\n\n /**\n * Set a font to use as a base. If no formatting is set on the text with a html tag, this will be used \n * Note: The font name either has to be a built in font on your printer or a font\n * that is registered on the label using 'registerFont'.\n */\n setFont(font: FontOption) {\n this.font = font\n }\n\n async commandForLanguage(language: PrinterLanguage, config?: PrintConfig): Promise<Command> {\n this.context = {\n config,\n language,\n generator: this.commandGeneratorFor(language)\n }\n\n let command: Command\n if(this.formatted) {\n command = this.generateFormattedText()\n } else {\n command = this.generatePlainText()\n }\n this.context = undefined\n \n return command\n }\n \n /**\n * Generate commands for formatted text\n * @returns \n */\n private generateFormattedText(): Command {\n if(!this.context) throw \"context-not-set\"\n \n const rootNode = parse(this.content)\n const { command } = this.generateFormattedRecursive(this.x, this.y, rootNode, this.font, [])\n return command\n }\n\n /**\n * Generate commands for plain text\n * @returns \n */\n private generatePlainText(): Command {\n const { command } = this.generatePlainTextCore(this.content, this.x, this.y, this.font)\n return command\n }\n\n /**\n * Iterats the nodes in a html text and generates text commands for it\n */\n private generateFormattedRecursive(initialX: number, initialY: number, rootNode: Node, font: FontOption, features: TextDecoration[]): {x: number, y: number, command: Command} {\n if(rootNode.nodeType == NodeType.TEXT_NODE) {\n const result = this.generatePlainTextCore(rootNode.innerText, initialX, initialY, font, features)\n return result\n } else {\n const elementNode = rootNode as HTMLElement\n const tag = elementNode.rawTagName\n\n if(tag == BREAK_TAG) {\n return {\n x: this.x,\n y: initialY + font.size + this.lineSpacing,\n command: this.context!.generator.commandGroup([])\n }\n }\n\n let commands: Command[] = []\n let currentX = initialX\n let currentY = initialY\n\n let baseFont = {...font}\n let baseFeatures = [...features]\n \n if(tag == UNDERLINE_TAG) {\n baseFeatures.push(\"underline\")\n } else if(STRIKE_TAG.includes(tag)) {\n baseFeatures.push(\"strike\")\n } else if(tag == BOLD_TAG) {\n baseFont.weight = BOLD_WEIGTH\n } else if(tag == ITALIC_TAG) {\n baseFont.style = \"italic\"\n }\n\n // Treat paragraphs as block-level elements: start and end on a new line.\n // Avoid adding an extra leading newline if the paragraph starts at the field origin.\n if(tag == PARAGRAPH_TAG) {\n if(initialX != this.x) {\n currentX = this.x\n currentY = initialY + baseFont.size + this.lineSpacing\n }\n }\n\n elementNode.childNodes.forEach(node => {\n const {x,y,command} = this.generateFormattedRecursive(currentX, currentY, node, baseFont, baseFeatures)\n currentX = x\n currentY = y\n commands.push(command)\n })\n\n if(tag == PARAGRAPH_TAG) {\n if(!this.endsWithBreak(elementNode)) {\n currentX = this.x\n currentY += baseFont.size + this.lineSpacing\n }\n }\n\n return {\n x: currentX,\n y: currentY,\n command: this.context!.generator.commandGroup(commands)\n }\n }\n }\n\n /**\n * Generate commands for plain text\n * @param config \n * @returns \n */\n private generatePlainTextCore(content: string, initialX: number, initialY: number, font: FontOption, features: TextDecoration[] = []): {x: number, y: number, command: Command} {\n if(!this.context) throw \"context-not-set\"\n\n const textWidhtFunction = this.textWidthFunction\n let fullWidth = textWidhtFunction(content, font)\n\n if(this.width) {\n const initialPadding = initialX - this.x\n // Because we may start from further in the row, the first rows width may be smaller\n let rowWidth = this.width - initialPadding\n // In theory rowWidth should not be negative, but for some reson it happens.. as a quick work around we make sure it is not negative\n if(rowWidth <= 0) {\n rowWidth = this.width\n initialX = this.x\n initialY += font.size + this.lineSpacing\n }\n\n // Make sure we don't print spaces at the beginig of a row\n if(initialX == this.x) {\n content = content.trimStart()\n fullWidth = textWidhtFunction(content, font)\n }\n\n // We may not start from the begining of the textbox so we have to offset\n // by our current position\n if(fullWidth <= rowWidth) {\n return {\n x: initialX + fullWidth,\n y: initialY,\n command: this.textCommand(content, initialX, initialY, font, features)\n }\n } else {\n const commands: Command[] = []\n \n let x = initialX\n let y = initialY\n let remainingContent = content\n let remainingWidth = fullWidth\n let currentHeight = 0\n\n let finalX = x\n let finalY = y\n\n do {\n // This will be the last row of the text. \n if(remainingWidth < rowWidth) {\n finalX = x + remainingWidth\n finalY = y\n\n commands.push(this.textCommand(remainingContent, x, y, font, features))\n remainingContent = \"\"\n } else {\n // On how many rows this text would fit\n let rows = remainingWidth / rowWidth\n\n // From the second row, all rows are full width\n rowWidth = this.width\n // Which caracter is the last if dividing into the right number of rows\n let rowEndIndex = Math.floor(remainingContent.length / rows)\n let originalRowEndIndex = rowEndIndex\n\n // This means we have to fit a relatively short text into\n // a lot of rows which can only happen if the row width is very small\n // in this case, we have to go to a new line\n // This is used to avoid having to calculate the width of the first character of the current text, to compare with the remainig length\n if(rowEndIndex == 0) {\n x = this.x\n y += font.size + this.lineSpacing\n continue\n }\n\n // Scenario 1: Current index is in a middle of row\n // I am iron m@n\n // End this row with the last words last character\n\n // Scneraio 2: Current index is space:\n // I am iron@man\n // No action, but to simplify code, we threat as scenario 1\n\n // Scenario 3: Current index is right before a sapce\n // I am iro@ man\n // Start next row from the first latter\n\n // Find the end of the last word\n while(\n ! (\n !isWhitespace(remainingContent.charAt(rowEndIndex)) &&\n (\n rowEndIndex == remainingContent.length - 1 ||\n isWhitespace(remainingContent.charAt(rowEndIndex + 1))\n )\n ) && rowEndIndex > 0\n ) { rowEndIndex -- }\n\n let nextRowStartIndex = rowEndIndex + 1\n // We didn't find a space, we split the text wherever we land\n if(rowEndIndex == 0) {\n rowEndIndex = originalRowEndIndex\n nextRowStartIndex = originalRowEndIndex + 1\n } else {\n while(\n isWhitespace(remainingContent.charAt(nextRowStartIndex)) && \n nextRowStartIndex < remainingContent.length\n ) { nextRowStartIndex ++ }\n }\n\n const thisRow = remainingContent.substring(0, rowEndIndex + 1)\n commands.push(this.textCommand(thisRow, x, y, font, features))\n\n if(nextRowStartIndex == remainingContent.length) {\n finalX = x + remainingWidth\n finalY = y\n }\n\n // Make sure to move the cursor back to the left side of the text box\n // as we may have started further into the row\n x = this.x\n y += font.size + this.lineSpacing\n currentHeight = y - this.y\n\n remainingContent = remainingContent.substring(nextRowStartIndex)\n remainingWidth = textWidhtFunction(remainingContent, font)\n }\n } while(\n // We don't have a height constraint or we are still within bounds \n // and there is still content \n // and we are supporting multiline\n (this.height == undefined || (currentHeight + font.size) <= this.height) &&\n (remainingContent != \"\") &&\n this.type == \"multiline\"\n )\n return {\n x: finalX,\n y: finalY,\n command: this.context!.generator.commandGroup(commands)\n }\n }\n } else {\n return {\n x: initialX + fullWidth,\n y: initialY,\n command: this.textCommand(content, initialX, initialY, font, features)\n }\n }\n }\n\n private textCommand(text: string, x: number, y: number, font: FontOption, features: TextDecoration[]) {\n if(!this.context) throw \"no-context\"\n const finalFontSize = dotToPoint(font.size, this.context!.config?.dpi ?? 203)\n const finalFont = this.getFontName(font)\n const finalX = Math.round(x)\n const finalY = Math.round(y)\n\n let commands: Command[] = []\n const textCommand = this.context!.generator.text(text, finalX, finalY, finalFont, finalFontSize)\n\n if(features.length == 0) {\n return textCommand\n } else {\n let lineHeight = font.size * 0.1\n let textWidth = this.textWidthFunction(text, font)\n\n if(features.includes(\"strike\")) {\n commands.push(this.textLineCommand(textWidth, x, y, lineHeight, 0.5, font.size))\n }\n\n if(features.includes(\"underline\")) {\n commands.push(this.textLineCommand(textWidth, x, y, lineHeight, 0.9, font.size))\n }\n\n commands.push(textCommand)\n }\n\n return this.context.generator.commandGroup(commands)\n }\n\n private textLineCommand(width: number, x: number, y: number, lineHeight: number, linePercentage: number, fontSize: number): Command {\n const sy = Math.round(y + (fontSize * linePercentage) - (lineHeight / 2))\n\n const sx = Math.round(x)\n return this.context!.generator.line(\n {x: sx, y: sy}, \n {x: sx + width, y: sy}, \n lineHeight)\n }\n\n private getFontName(font: FontOption) {\n if(!this.context) throw \"no-context\"\n if(font.name == \"default\") {\n return \"default\"\n } else {\n return this.context!.config?.getFontName(font)!\n }\n }\n\n private get textWidthFunction() {\n if(this.font.name == \"default\") {\n return this.defaultTextWidth\n } else {\n return this.context?.config?.textWidth ?? this.defaultTextWidth\n }\n }\n\n /**\n * This function is used to calculate the font size if no\n * print config is provided. This will asume that the font has square characters\n */\n private defaultTextWidth(text: string, font: FontOption) {\n return text.length * font.size\n }\n}","import { Command, PrinterLanguage } from \"@/commands\";\nimport { PrintConfig } from \"../Printable\";\nimport LabelField from \"./LabelField\"\nimport { Alignment, BarcodeHumanReable, BarcodeType, Rotation } from \"@/commands/tspl\";\n\nexport default class BarCode extends LabelField {\n private readonly content: string\n private readonly x: number\n private readonly y: number\n private readonly type: BarcodeType\n private readonly height: number\n private rotation: Rotation\n private humanReadable: BarcodeHumanReable \n private readonly alignment: Alignment\n\n constructor(content: string, x: number, y: number, type: BarcodeType, height: number) {\n super()\n this.content = content\n this.x = x\n this.y = y\n this.type = type\n this.height = height\n this.rotation = 0\n this.humanReadable = \"none\"\n this.alignment = \"left\"\n }\n\n setRotation(rotation: Rotation) {\n this.rotation = rotation\n }\n\n setHumanReadable(humanReadable: BarcodeHumanReable) {\n this.humanReadable = humanReadable\n }\n\n async commandForLanguage(language: PrinterLanguage, _config?: PrintConfig | undefined): Promise<Command> {\n return await this.commandGeneratorFor(language).barCode(this.content, this.x, this.y, this.type, this.height, this.rotation, this.humanReadable, this.alignment)\n }\n}","import { Command, PrinterLanguage } from \"@/commands\";\nimport { PrintConfig } from \"../Printable\";\nimport LabelField from \"./LabelField\";\nimport ImageUtils, { BitmapLike } from \"@/helpers/ImageUtils\";\n\nexport default class Image extends LabelField {\n /**\n * X coordinate in dots\n */\n private readonly x: number\n /**\n * Y coordinate in dots\n */\n private readonly y: number\n\n private readonly image: BitmapLike\n\n constructor(x: number, y: number, image: BitmapLike) {\n super()\n this.x = x\n this.y = y\n this.image = image\n }\n\n async commandForLanguage(language: PrinterLanguage, _config?: PrintConfig | undefined): Promise<Command> {\n return await this.commandGeneratorFor(language).image(this.image, this.x, this.y)\n }\n\n /**\n * Create an image field for an image\n * @param image \n * @param x \n * @param y \n * @param width \n * @param height \n * @returns \n */\n static async create(image: string|Blob, x: number, y: number, width?: number, height?: number): Promise<Image> {\n const bitmap = await ImageUtils.getBWBitmap(image, width, height)\n\n return new Image(x, y, bitmap)\n }\n}","import { Command, PrinterLanguage } from \"@/commands\";\nimport { PrintConfig } from \"../Printable\";\nimport LabelField from \"./LabelField\";\n\nexport default class QRCode extends LabelField {\n private readonly content: string\n private readonly x: number\n private readonly y: number\n private readonly width: number\n\n constructor(content: string, x: number, y: number, width: number) {\n super()\n this.content = content\n this.x = x\n this.y = y\n this.width = width\n }\n\n async commandForLanguage(language: PrinterLanguage, config?: PrintConfig | undefined): Promise<Command> {\n return await this.commandGeneratorFor(language).qrCode(this.content, this.width, this.x, this.y)\n }\n}","import { Command, PrinterLanguage } from \"@/commands\";\nimport { isWhitespace } from \"@/helpers/StringUtils\";\nimport LabelField from \"./LabelField\";\nimport Line from \"./Line\";\nimport Text from \"./Text\";\nimport { PrintConfig } from \"../Printable\";\nimport { FontOption } from \"../types\";\n\nexport type TableCellContent = string\n\nexport type TableSize = {\n width?: number,\n height?: number\n}\n\ntype SizeSpec = number|undefined\n\nexport type TableOptions = {\n size?: TableSize,\n columnWidths?: SizeSpec[],\n rowHeights?: SizeSpec[],\n lineThickness?: number,\n cellPadding?: number,\n formatted?: boolean,\n font?: FontOption\n}\n\nexport default class Table extends LabelField {\n private readonly x: number\n private readonly y: number\n private readonly rows: TableCellContent[][]\n\n private size: TableSize|undefined\n private columnWidths: SizeSpec[]|undefined\n private rowHeights: SizeSpec[]|undefined\n\n private lineThickness: number\n private cellPadding: number\n private formatted: boolean\n private font: FontOption\n\n constructor(x: number, y: number, rows: TableCellContent[][], options: TableOptions = {}) {\n super()\n this.x = x\n this.y = y\n this.rows = rows\n\n this.size = options.size\n this.columnWidths = options.columnWidths\n this.rowHeights = options.rowHeights\n this.lineThickness = options.lineThickness ?? 2\n this.cellPadding = options.cellPadding ?? 4\n this.formatted = options.formatted ?? true\n this.font = options.font ?? {name: \"default\", size: 10}\n }\n\n setSize(size: TableSize) {\n this.size = size\n }\n\n setColumnWidths(widths: SizeSpec[]) {\n this.columnWidths = widths\n }\n\n setRowHeights(heights: SizeSpec[]) {\n this.rowHeights = heights\n }\n\n setLineThickness(thickness: number) {\n this.lineThickness = thickness\n }\n\n setCellPadding(padding: number) {\n this.cellPadding = padding\n }\n\n setFormatted(formatted: boolean) {\n this.formatted = formatted\n }\n\n setFont(font: FontOption) {\n this.font = font\n }\n\n async commandForLanguage(language: PrinterLanguage, config?: PrintConfig): Promise<Command> {\n // Table rendering is implemented by composing existing primitives:\n // - Text fields for cell contents\n // - Line fields for the grid\n const generator = this.commandGeneratorFor(language)\n\n const rowCount = this.rows.length\n const colCount = Math.max(0, ...this.rows.map(r => r.length))\n\n // Resolve column widths.\n // If the overall table width is provided, unspecified columns share the remaining width.\n // Otherwise, unspecified columns are measured from content.\n const resolvedColumnWidths = this.resolveTrackSizes({\n trackCount: colCount,\n explicitSizes: this.columnWidths,\n total: this.size?.width,\n measure: (i) => this.measureAutoColumnWidth(i, colCount, config)\n })\n\n // Resolve row heights.\n // If the overall table height is provided, unspecified rows share the remaining height.\n // Otherwise, unspecified rows are measured from content and the resolved column widths.\n const resolvedRowHeights = this.resolveTrackSizes({\n trackCount: rowCount,\n explicitSizes: this.rowHeights,\n total: this.size?.height,\n measure: (i) => this.measureAutoRowHeight(i, resolvedColumnWidths, config)\n })\n\n // Convert widths/heights into absolute X/Y positions.\n const xPositions = this.accumulatePositions(this.x, resolvedColumnWidths)\n const yPositions = this.accumulatePositions(this.y, resolvedRowHeights)\n\n // We generate an internal list of LabelFields and then group their commands.\n // This ensures we reuse the exact behavior of the existing Text and Line fields.\n const fields: LabelField[] = []\n\n // Create a Text field for each cell.\n // Cell text is constrained to the cell content box, which enables wrapping.\n for(let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\n for(let colIndex = 0; colIndex < colCount; colIndex++) {\n const cellContent = this.rows[rowIndex]?.[colIndex] ?? \"\"\n const cellX = xPositions[colIndex]\n const cellY = yPositions[rowIndex]\n const cellWidth = resolvedColumnWidths[colIndex]\n const cellHeight = resolvedRowHeights[rowIndex]\n\n // Apply padding so text doesn't touch grid lines.\n const textX = cellX + this.cellPadding\n const textY = cellY + this.cellPadding\n const textWidth = Math.max(1, cellWidth - (this.cellPadding * 2))\n const textHeight = Math.max(1, cellHeight - (this.cellPadding * 2))\n\n const text = new Text(cellContent, textX, textY, this.formatted)\n text.setFont(this.font)\n // Multi-line text behavior matches the existing Text field:\n // - wraps when width is exceeded\n // - clips once the height constraint is reached\n text.setMultiLine(textWidth, textHeight)\n fields.push(text)\n }\n }\n\n // Total table dimensions (after resolving track sizes).\n const totalWidth = resolvedColumnWidths.reduce((a, b) => a + b, 0)\n const totalHeight = resolvedRowHeights.reduce((a, b) => a + b, 0)\n\n // Vertical grid lines (including left and right borders).\n for(let colIndex = 0; colIndex <= colCount; colIndex++) {\n const sx = colIndex == colCount ? this.x + totalWidth : xPositions[colIndex]\n fields.push(new Line(\n {x: sx, y: this.y},\n {x: sx, y: this.y + totalHeight},\n this.lineThickness\n ))\n }\n\n // Horizontal grid lines (including top and bottom borders).\n for(let rowIndex = 0; rowIndex <= rowCount; rowIndex++) {\n const sy = rowIndex == rowCount ? this.y + totalHeight : yPositions[rowIndex]\n fields.push(new Line(\n {x: this.x, y: sy},\n {x: this.x + totalWidth, y: sy},\n this.lineThickness\n ))\n }\n\n // Finally, generate and group all underlying commands.\n const commandList = await Promise.all(fields.map(field => field.commandForLanguage(language, config)))\n return generator.commandGroup(commandList)\n }\n\n private accumulatePositions(start: number, sizes: number[]): number[] {\n // Converts a list of track sizes (widths/heights) into absolute positions.\n // Returned array contains the starting coordinate for each track.\n const positions: number[] = []\n let current = start\n for(const s of sizes) {\n positions.push(current)\n current += s\n }\n return positions\n }\n\n private resolveTrackSizes(params: {\n trackCount: number,\n explicitSizes?: SizeSpec[],\n total?: number,\n measure: (trackIndex: number) => number\n }): number[] {\n if(params.trackCount == 0) return []\n \n // Resolves row/column sizes.\n // - If an explicit size is provided, it is used.\n // - If overall total is provided, any unspecified tracks share remaining space equally.\n // - Otherwise, unspecified tracks are measured from content.\n const sizes: SizeSpec[] = new Array(params.trackCount).fill(undefined)\n\n if(params.explicitSizes) {\n for(let i = 0; i < Math.min(params.trackCount, params.explicitSizes.length); i++) {\n sizes[i] = params.explicitSizes[i]\n }\n }\n\n if(params.total != undefined) {\n // Fixed + flexible: distribute remaining space among tracks with undefined size.\n const fixedTotal = sizes.reduce((sum: number, s) => sum + (s ?? 0), 0)\n const flexibleCount = sizes.filter(s => s == undefined).length\n\n const remaining = Math.max(0, params.total - fixedTotal)\n const flexSize = flexibleCount == 0 ? 0 : remaining / flexibleCount\n\n return sizes.map((s, i) => Math.max(1, s ?? flexSize ?? params.measure(i)))\n }\n\n return sizes.map((s, i) => Math.max(1, s ?? params.measure(i)))\n }\n\n private measureAutoColumnWidth(columnIndex: number, colCount: number, config?: PrintConfig): number {\n // Content-based width measurement for an auto-sized column.\n // This is a heuristic: it uses single-line text width + padding.\n const contentWidths: number[] = []\n\n for(const row of this.rows) {\n const content = row?.[columnIndex] ?? \"\"\n const plain = this.toPlainText(content)\n const w = this.textWidth(plain, config)\n contentWidths.push(w)\n }\n\n const maxContentWidth = contentWidths.length == 0 ? 0 : Math.max(...contentWidths)\n\n const minWidth = this.font.size\n const measured = Math.max(minWidth, maxContentWidth) + (this.cellPadding * 2)\n\n if(colCount == 0) return measured\n return measured\n }\n\n private measureAutoRowHeight(rowIndex: number, columnWidths: number[], config?: PrintConfig): number {\n // Content-based height measurement for an auto-sized row.\n // We estimate how many wrapped lines are needed for each cell, then take the max.\n const row = this.rows[rowIndex] ?? []\n const contentHeights: number[] = []\n\n for(let colIndex = 0; colIndex < columnWidths.length; colIndex++) {\n const content = row[colIndex] ?? \"\"\n const plain = this.toPlainText(content)\n const availableWidth = Math.max(1, columnWidths[colIndex] - (this.cellPadding * 2))\n const lineCount = this.estimateLineCount(plain, availableWidth, config)\n const lineHeight = this.font.size + 1\n contentHeights.push(lineCount * lineHeight)\n }\n\n const maxContentHeight = contentHeights.length == 0 ? this.font.size : Math.max(...contentHeights)\n return maxContentHeight + (this.cellPadding * 2)\n }\n\n private estimateLineCount(content: string, width: number, config?: PrintConfig): number {\n // Estimates wrapped line count using word-wrapping.\n // This doesn't try to exactly match printer rendering; it exists to auto-size rows.\n const normalized = content.replace(\"\\n\", \" \")\n\n if(normalized.trim() == \"\") return 1\n\n const words: string[] = []\n let buffer = \"\"\n\n for(let i = 0; i < normalized.length; i++) {\n const ch = normalized.charAt(i)\n if(isWhitespace(ch)) {\n if(buffer != \"\") {\n words.push(buffer)\n buffer = \"\"\n }\n continue\n }\n buffer += ch\n }\n\n if(buffer != \"\") words.push(buffer)\n\n let lines = 1\n let currentLine = \"\"\n\n for(const word of words) {\n const candidate = currentLine == \"\" ? word : `${currentLine} ${word}`\n\n if(this.textWidth(candidate, config) <= width) {\n currentLine = candidate\n } else {\n if(currentLine == \"\") {\n const charsPerLine = Math.max(1, Math.floor(width / Math.max(1, this.font.size)))\n const neededLines = Math.ceil(word.length / charsPerLine)\n lines += neededLines - 1\n currentLine = word.substring((neededLines - 1) * charsPerLine)\n } else {\n lines += 1\n currentLine = word\n }\n }\n }\n\n return Math.max(1, lines)\n }\n\n private textWidth(text: string, config?: PrintConfig): number {\n // Measures text width in dots.\n // If a font is registered and PrintConfig is provided, use accurate font metrics.\n // Otherwise fall back to a simple monospace approximation.\n if(this.font.name == \"default\" || !config) {\n return text.length * this.font.size\n }\n return config.textWidth(text, this.font)\n }\n\n private toPlainText(content: string): string {\n // Measurement helpers should ignore formatting.\n // This strips basic HTML tags used by the Text field's formatting support.\n return content.replace(/<[^>]*>/g, \"\")\n }\n}\n"],"mappings":"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","names":["pointsPerInch","buffer","image","target","src","imageData","buffer","url","image","target","bytes","bitmap","widthDots","bitmap","image","image","bytes","bytes","stringHelper","bytes","buffer","factory","Image","Image","image","bitmap","buffer"]}
|