@bobfrankston/brother-label 1.0.8 → 1.0.10
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/api.d.ts.map +1 -1
- package/api.js +2 -12
- package/api.js.map +1 -1
- package/api.ts +2 -12
- package/package.json +1 -1
package/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAC5C,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,UAAU,CAAC;AAEnD,MAAM,WAAW,aAAa;IAC1B,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAEzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,EAAE,CAAC,EAAE,MAAM,CAAC;IAGZ,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IACxB,KAAK,EAAE,MAAM,CAAC;CACjB;AA0BD,wBAAgB,SAAS,IAAI,aAAa,CAczC;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,CAI9D;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAGD,wBAAsB,YAAY,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAuB3D;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAC5C,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,UAAU,CAAC;AAEnD,MAAM,WAAW,aAAa;IAC1B,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAEzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,EAAE,CAAC,EAAE,MAAM,CAAC;IAGZ,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IACxB,KAAK,EAAE,MAAM,CAAC;CACjB;AA0BD,wBAAgB,SAAS,IAAI,aAAa,CAczC;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,CAI9D;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAGD,wBAAsB,YAAY,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAuB3D;AAsVD,wBAAsB,MAAM,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAInE;AAED,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAMvE"}
|
package/api.js
CHANGED
|
@@ -298,19 +298,9 @@ $ticketXml = @"
|
|
|
298
298
|
<psf:Feature name="psk:PageMediaType">
|
|
299
299
|
<psf:Option name="psk:Label" />
|
|
300
300
|
</psf:Feature>
|
|
301
|
-
<psf:Feature name="
|
|
302
|
-
<psf:Option name="
|
|
301
|
+
<psf:Feature name="ns0001:JobRollCutAtEndOfJob">
|
|
302
|
+
<psf:Option name="ns0001:Cut" />
|
|
303
303
|
</psf:Feature>
|
|
304
|
-
<psf:Feature name="ns0001:JobRollCutSheet">
|
|
305
|
-
<psf:Option name="ns0001:CutSheet">
|
|
306
|
-
<psf:ScoredProperty name="ns0001:CutSheetCount">
|
|
307
|
-
<psf:ParameterRef name="ns0001:JobCutSheetCount" />
|
|
308
|
-
</psf:ScoredProperty>
|
|
309
|
-
</psf:Option>
|
|
310
|
-
</psf:Feature>
|
|
311
|
-
<psf:ParameterInit name="ns0001:JobCutSheetCount">
|
|
312
|
-
<psf:Value xsi:type="xsd:integer">1</psf:Value>
|
|
313
|
-
</psf:ParameterInit>
|
|
314
304
|
</psf:PrintTicket>
|
|
315
305
|
"@
|
|
316
306
|
|
package/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["api.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Brother Label Printer API\r\n * Programmatic interface for printing labels on Brother P-touch printers\r\n */\r\n\r\nimport * as fs from \"fs\";\r\nimport * as path from \"path\";\r\nimport * as os from \"os\";\r\nimport { renderHtmlFile, renderHtmlString, closeBrowser } from \"./render.js\";\r\nimport { Jimp, loadFont, measureText, measureTextHeight } from \"jimp\";\r\nimport { spawn } from \"child_process\";\r\nimport QRCode from \"qrcode\";\r\n\r\n// Types\r\nexport type TapeSize = 6 | 9 | 12 | 18 | 24;\r\nexport type Orientation = \"landscape\" | \"portrait\";\r\n\r\nexport interface PrinterConfig {\r\n defaultTape?: TapeSize;\r\n defaultPrinter?: string;\r\n}\r\n\r\nexport interface PrinterInfo {\r\n name: string;\r\n}\r\n\r\nexport interface PrintOptions {\r\n // Content (exactly one required)\r\n text?: string;\r\n html?: string;\r\n htmlPath?: string;\r\n textFile?: string;\r\n imagePath?: string;\r\n imageBuffer?: Buffer;\r\n qr?: string; // QR code data to encode\r\n\r\n // Settings\r\n tape?: TapeSize;\r\n printer?: string;\r\n orientation?: Orientation;\r\n length?: number; // explicit length in mm\r\n basePath?: string; // base path for inline HTML resources\r\n aspect?: string; // width:height ratio for HTML (e.g., \"3.5:2\")\r\n qrLabel?: string; // optional text label beside QR code\r\n}\r\n\r\nexport interface PrintResult {\r\n image: Buffer;\r\n}\r\n\r\n// Constants\r\nconst CONFIG_PATH = path.join(os.homedir(), \".brother-label.json\");\r\nconst DEFAULT_PRINTER = \"Brother PT-P710BT\";\r\nconst PRINT_DPI = 300; // High resolution for quality output\r\n\r\n// Tape sizes: height is printable area in pixels at 300 DPI\r\nconst TAPE_SIZES: Record<TapeSize, { width: number; height: number }> = {\r\n 6: { width: 1137, height: 56 }, // 3.79\" x 0.19\" @ 300 DPI\r\n 9: { width: 1137, height: 84 }, // 3.79\" x 0.28\" @ 300 DPI\r\n 12: { width: 1137, height: 113 }, // 3.79\" x 0.38\" @ 300 DPI\r\n 18: { width: 1137, height: 169 }, // 3.79\" x 0.56\" @ 300 DPI\r\n 24: { width: 1137, height: 213 }, // 3.79\" x 0.71\" @ 300 DPI\r\n};\r\n\r\n// Brother CustomMediaSize names and widths in microns\r\nconst MEDIA_OPTIONS: Record<TapeSize, { name: string; width: number }> = {\r\n 6: { name: \"CustomMediaSize257\", width: 5900 },\r\n 9: { name: \"CustomMediaSize258\", width: 9000 },\r\n 12: { name: \"CustomMediaSize259\", width: 11900 },\r\n 18: { name: \"CustomMediaSize260\", width: 18100 },\r\n 24: { name: \"CustomMediaSize261\", width: 24000 },\r\n};\r\n\r\n// Config functions\r\nexport function getConfig(): PrinterConfig {\r\n try {\r\n if (fs.existsSync(CONFIG_PATH)) {\r\n const raw = JSON.parse(fs.readFileSync(CONFIG_PATH, \"utf-8\"));\r\n // Handle legacy format where tape was stored as \"24mm\" string\r\n if (typeof raw.defaultTape === \"string\") {\r\n raw.defaultTape = parseInt(raw.defaultTape.replace(\"mm\", \"\"), 10) as TapeSize;\r\n }\r\n return raw;\r\n }\r\n } catch {\r\n // Ignore config errors\r\n }\r\n return {};\r\n}\r\n\r\nexport function setConfig(config: Partial<PrinterConfig>): void {\r\n const current = getConfig();\r\n const merged = { ...current, ...config };\r\n fs.writeFileSync(CONFIG_PATH, JSON.stringify(merged, null, 2));\r\n}\r\n\r\nexport function getConfigPath(): string {\r\n return CONFIG_PATH;\r\n}\r\n\r\n// Printer listing\r\nexport async function listPrinters(): Promise<PrinterInfo[]> {\r\n return new Promise((resolve, reject) => {\r\n const ps = spawn(\"powershell\", [\r\n \"-Command\",\r\n \"Get-Printer | Where-Object { $_.Name -like '*Brother*' -or $_.Name -like '*PT*' -or $_.Name -like '*QL*' } | Select-Object -ExpandProperty Name\"\r\n ], { stdio: \"pipe\" });\r\n\r\n let stdout = \"\";\r\n let stderr = \"\";\r\n ps.stdout.on(\"data\", (data) => { stdout += data.toString(); });\r\n ps.stderr.on(\"data\", (data) => { stderr += data.toString(); });\r\n\r\n ps.on(\"close\", (code) => {\r\n if (code !== 0) {\r\n reject(new Error(`Failed to list printers: ${stderr}`));\r\n return;\r\n }\r\n const printers = stdout.trim().split(\"\\n\")\r\n .filter(p => p.trim())\r\n .map(name => ({ name: name.trim() }));\r\n resolve(printers);\r\n });\r\n });\r\n}\r\n\r\n// Calculate HTML viewport dimensions from tape height and optional aspect ratio\r\nfunction getHtmlDimensions(tapeHeight: number, aspect?: string): { width?: number; height: number } {\r\n if (!aspect) {\r\n // Auto-detect width from content\r\n return { width: undefined, height: tapeHeight };\r\n }\r\n\r\n // Parse aspect ratio \"width:height\" or \"width/height\" (e.g., \"3.5:2\" or \"3.5/2\")\r\n const separator = aspect.includes(\"/\") ? \"/\" : \":\";\r\n const parts = aspect.split(separator);\r\n if (parts.length !== 2) {\r\n throw new Error(`Invalid aspect ratio: ${aspect}. Use format \"width:height\" or \"width/height\"`);\r\n }\r\n const aspectWidth = parseFloat(parts[0]);\r\n const aspectHeight = parseFloat(parts[1]);\r\n if (isNaN(aspectWidth) || isNaN(aspectHeight) || aspectHeight === 0) {\r\n throw new Error(`Invalid aspect ratio: ${aspect}. Use format \"width:height\" (e.g., \"3.5:2\")`);\r\n }\r\n\r\n // Scale so height fits tape, width is proportional\r\n const height = tapeHeight;\r\n const width = Math.round(tapeHeight * (aspectWidth / aspectHeight));\r\n return { width, height };\r\n}\r\n\r\n// Validation\r\nfunction validateOptions(options: PrintOptions): void {\r\n const contentFields = [\r\n options.text,\r\n options.html,\r\n options.htmlPath,\r\n options.textFile,\r\n options.imagePath,\r\n options.imageBuffer,\r\n options.qr,\r\n ].filter(f => f !== undefined);\r\n\r\n if (contentFields.length === 0) {\r\n throw new Error(\"No content provided. Specify one of: text, html, htmlPath, textFile, imagePath, imageBuffer, qr\");\r\n }\r\n if (contentFields.length > 1) {\r\n throw new Error(\"Multiple content options provided. Specify exactly one.\");\r\n }\r\n\r\n if (options.tape !== undefined && !TAPE_SIZES[options.tape]) {\r\n throw new Error(`Invalid tape size: ${options.tape}. Valid sizes: 6, 9, 12, 18, 24`);\r\n }\r\n}\r\n\r\n// Resolve effective settings from options + config + defaults\r\nfunction resolveSettings(options: PrintOptions): { tape: TapeSize; printer: string } {\r\n const config = getConfig();\r\n return {\r\n tape: options.tape ?? config.defaultTape ?? 24,\r\n printer: options.printer ?? config.defaultPrinter ?? DEFAULT_PRINTER,\r\n };\r\n}\r\n\r\n// Render text to image buffer\r\nasync function renderText(text: string, tape: TapeSize): Promise<Buffer> {\r\n const tapeSize = TAPE_SIZES[tape];\r\n const targetHeight = tapeSize.height;\r\n const lines = text.split(\"\\\\n\").join(\"\\n\");\r\n\r\n // Load largest font for quality\r\n const fontDir = path.join(path.dirname(new URL(import.meta.url).pathname).replace(/^\\/([A-Z]:)/, \"$1\"), \"node_modules/@jimp/plugin-print/fonts/open-sans\");\r\n const fontPath = path.join(fontDir, \"open-sans-128-black\", \"open-sans-128-black.fnt\");\r\n const font = await loadFont(fontPath);\r\n\r\n // Measure text\r\n const textWidth = measureText(font, lines);\r\n const textHeight = measureTextHeight(font, lines, textWidth + 100);\r\n\r\n // Create temp image for text\r\n const padding = 10;\r\n const imgWidth = textWidth + padding * 2;\r\n const imgHeight = textHeight + padding * 2;\r\n\r\n const tempImage = new Jimp({ width: imgWidth, height: imgHeight, color: 0xffffffff });\r\n tempImage.print({ font, x: padding, y: padding, text: lines });\r\n\r\n // Scale to fit tape height\r\n const scale = targetHeight / imgHeight;\r\n const finalWidth = Math.round(imgWidth * scale);\r\n const finalHeight = Math.round(imgHeight * scale);\r\n tempImage.resize({ w: finalWidth, h: finalHeight });\r\n\r\n // Create final image with padding\r\n const hPadding = Math.round(targetHeight * 0.2);\r\n const outputWidth = finalWidth + hPadding * 2;\r\n const image = new Jimp({ width: outputWidth, height: targetHeight, color: 0xffffffff });\r\n\r\n const xOffset = hPadding;\r\n const yOffset = Math.round((targetHeight - finalHeight) / 2);\r\n image.composite(tempImage, xOffset, yOffset);\r\n\r\n return image.getBuffer(\"image/png\");\r\n}\r\n\r\n// Render QR code to image buffer\r\nasync function renderQr(data: string, tape: TapeSize, labelText?: string): Promise<Buffer> {\r\n const tapeSize = TAPE_SIZES[tape];\r\n const targetHeight = tapeSize.height;\r\n const qrSize = Math.floor(targetHeight * 0.95);\r\n\r\n // Margins in pixels at PRINT_DPI (3mm left, 4mm right)\r\n const pxPerMm = PRINT_DPI / 25.4;\r\n const leftMargin = Math.round(3 * pxPerMm);\r\n const rightMargin = Math.round(4 * pxPerMm);\r\n\r\n // Generate QR code at high resolution\r\n const qrBuffer = await QRCode.toBuffer(data, {\r\n type: \"png\",\r\n width: qrSize,\r\n margin: 0,\r\n errorCorrectionLevel: \"M\",\r\n color: { dark: \"#000000\", light: \"#ffffff\" },\r\n });\r\n\r\n const qrImage = await Jimp.read(qrBuffer);\r\n\r\n if (!labelText) {\r\n // QR only\r\n const outputWidth = leftMargin + qrSize + rightMargin;\r\n const image = new Jimp({ width: outputWidth, height: targetHeight, color: 0xffffffff });\r\n const yOffset = Math.floor((targetHeight - qrSize) / 2);\r\n image.composite(qrImage, leftMargin, yOffset);\r\n return image.getBuffer(\"image/png\");\r\n }\r\n\r\n // QR + text label\r\n const fontDir = path.join(path.dirname(new URL(import.meta.url).pathname).replace(/^\\/([A-Z]:)/, \"$1\"), \"node_modules/@jimp/plugin-print/fonts/open-sans\");\r\n const fontPath = path.join(fontDir, \"open-sans-64-black\", \"open-sans-64-black.fnt\");\r\n const font = await loadFont(fontPath);\r\n\r\n const textWidth = measureText(font, labelText);\r\n const textHeight = measureTextHeight(font, labelText, textWidth + 50);\r\n\r\n // Scale text to fit beside QR\r\n const maxTextHeight = targetHeight * 0.8;\r\n const textScale = Math.min(1, maxTextHeight / textHeight);\r\n const scaledTextWidth = Math.round(textWidth * textScale);\r\n const scaledTextHeight = Math.round(textHeight * textScale);\r\n\r\n // Create text image\r\n const textImg = new Jimp({ width: textWidth + 20, height: textHeight + 20, color: 0xffffffff });\r\n textImg.print({ font, x: 10, y: 10, text: labelText });\r\n if (textScale < 1) {\r\n textImg.resize({ w: scaledTextWidth, h: scaledTextHeight });\r\n }\r\n\r\n // Compose: QR on left, text on right\r\n const gap = Math.floor(targetHeight * 0.15);\r\n const outputWidth = leftMargin + qrSize + gap + scaledTextWidth + rightMargin;\r\n const image = new Jimp({ width: outputWidth, height: targetHeight, color: 0xffffffff });\r\n\r\n const qrY = Math.floor((targetHeight - qrSize) / 2);\r\n image.composite(qrImage, leftMargin, qrY);\r\n\r\n const textY = Math.floor((targetHeight - scaledTextHeight) / 2);\r\n image.composite(textImg, leftMargin + qrSize + gap, textY);\r\n\r\n return image.getBuffer(\"image/png\");\r\n}\r\n\r\n// Render content to image buffer\r\nasync function renderContent(options: PrintOptions, tape: TapeSize): Promise<Buffer> {\r\n const tapeSize = TAPE_SIZES[tape];\r\n\r\n if (options.text !== undefined) {\r\n return renderText(options.text, tape);\r\n }\r\n\r\n if (options.textFile !== undefined) {\r\n const text = fs.readFileSync(options.textFile, \"utf-8\");\r\n return renderText(text, tape);\r\n }\r\n\r\n if (options.html !== undefined) {\r\n const { width, height } = getHtmlDimensions(tapeSize.height, options.aspect);\r\n const buffer = await renderHtmlString(options.html, { width, height, tapeMm: tape }, options.basePath);\r\n await closeBrowser();\r\n return buffer;\r\n }\r\n\r\n if (options.htmlPath !== undefined) {\r\n const { width, height } = getHtmlDimensions(tapeSize.height, options.aspect);\r\n const buffer = await renderHtmlFile(options.htmlPath, { width, height, tapeMm: tape });\r\n await closeBrowser();\r\n return buffer;\r\n }\r\n\r\n if (options.imagePath !== undefined) {\r\n return fs.readFileSync(options.imagePath);\r\n }\r\n\r\n if (options.imageBuffer !== undefined) {\r\n return options.imageBuffer;\r\n }\r\n\r\n if (options.qr !== undefined) {\r\n return renderQr(options.qr, tape, options.qrLabel);\r\n }\r\n\r\n throw new Error(\"No content to render\");\r\n}\r\n\r\n// Print single image buffer to printer\r\nasync function printBuffer(imageBuffer: Buffer, printer: string, tape: TapeSize): Promise<void> {\r\n const media = MEDIA_OPTIONS[tape];\r\n\r\n const tempPath = path.join(os.tmpdir(), `label-${Date.now()}.png`);\r\n fs.writeFileSync(tempPath, imageBuffer);\r\n\r\n try {\r\n await new Promise<void>((resolve, reject) => {\r\n const psScript = `\r\nAdd-Type -AssemblyName System.Drawing\r\nAdd-Type -AssemblyName System.Printing\r\nAdd-Type -AssemblyName ReachFramework\r\nAdd-Type -AssemblyName PresentationCore\r\n\r\n$img = [System.Drawing.Image]::FromFile('${tempPath.replace(/\\\\/g, \"\\\\\\\\\")}')\r\n\r\n$DPI = ${PRINT_DPI}\r\n$MICRONS_PER_INCH = 25400\r\n\r\n$labelLengthMicrons = [int]($img.Width / $DPI * $MICRONS_PER_INCH) + 3000 # +2mm offset +1mm buffer\r\n$tapeWidthMicrons = ${media.width}\r\n\r\n$imgWidthWpf = $img.Width / $DPI * 96\r\n$imgHeightWpf = $img.Height / $DPI * 96\r\n\r\n$ticketXml = @\"\r\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<psf:PrintTicket xmlns:psf=\"http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework\"\r\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" version=\"1\"\r\n xmlns:psk=\"http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords\"\r\n xmlns:ns0001=\"http://schemas.brother.info/mfc/printing/2006/11/printschemakeywords\">\r\n <psf:Feature name=\"psk:PageMediaSize\">\r\n <psf:Option name=\"ns0001:${media.name}\">\r\n <psf:ScoredProperty name=\"psk:MediaSizeWidth\">\r\n <psf:Value xsi:type=\"xsd:integer\">${media.width}</psf:Value>\r\n </psf:ScoredProperty>\r\n <psf:ScoredProperty name=\"psk:MediaSizeHeight\">\r\n <psf:ParameterRef name=\"psk:PageMediaSizeMediaSizeHeight\" />\r\n </psf:ScoredProperty>\r\n </psf:Option>\r\n </psf:Feature>\r\n <psf:ParameterInit name=\"psk:PageMediaSizeMediaSizeHeight\">\r\n <psf:Value xsi:type=\"xsd:integer\">$labelLengthMicrons</psf:Value>\r\n </psf:ParameterInit>\r\n <psf:Feature name=\"psk:PageOrientation\">\r\n <psf:Option name=\"psk:Landscape\" />\r\n </psf:Feature>\r\n <psf:Feature name=\"ns0001:PageRollFeedToEndOfSheet\">\r\n <psf:Option name=\"ns0001:FeedToImageEdge\" />\r\n </psf:Feature>\r\n <psf:Feature name=\"psk:PageMediaType\">\r\n <psf:Option name=\"psk:Label\" />\r\n </psf:Feature>\r\n <psf:Feature name=\"psk:JobRollCutAtEndOfJob\">\r\n <psf:Option name=\"psk:None\" />\r\n </psf:Feature>\r\n <psf:Feature name=\"ns0001:JobRollCutSheet\">\r\n <psf:Option name=\"ns0001:CutSheet\">\r\n <psf:ScoredProperty name=\"ns0001:CutSheetCount\">\r\n <psf:ParameterRef name=\"ns0001:JobCutSheetCount\" />\r\n </psf:ScoredProperty>\r\n </psf:Option>\r\n </psf:Feature>\r\n <psf:ParameterInit name=\"ns0001:JobCutSheetCount\">\r\n <psf:Value xsi:type=\"xsd:integer\">1</psf:Value>\r\n </psf:ParameterInit>\r\n</psf:PrintTicket>\r\n\"@\r\n\r\n$xmlBytes = [System.Text.Encoding]::UTF8.GetBytes($ticketXml)\r\n$memStream = New-Object System.IO.MemoryStream(,$xmlBytes)\r\n$ticket = New-Object System.Printing.PrintTicket($memStream)\r\n\r\n$server = New-Object System.Printing.LocalPrintServer\r\n$queue = $server.GetPrintQueue('${printer}')\r\n\r\n$xpsPath = [System.IO.Path]::GetTempFileName() + \".xps\"\r\n\r\n$pageWidth = $labelLengthMicrons / $MICRONS_PER_INCH * 96\r\n$pageHeight = $tapeWidthMicrons / $MICRONS_PER_INCH * 96\r\n\r\n$package = [System.IO.Packaging.Package]::Open($xpsPath, [System.IO.FileMode]::Create)\r\n$xpsDoc = New-Object System.Windows.Xps.Packaging.XpsDocument($package)\r\n$writer = [System.Windows.Xps.Packaging.XpsDocument]::CreateXpsDocumentWriter($xpsDoc)\r\n\r\n$visual = New-Object System.Windows.Media.DrawingVisual\r\n$dc = $visual.RenderOpen()\r\n\r\n$bitmapImg = New-Object System.Windows.Media.Imaging.BitmapImage\r\n$bitmapImg.BeginInit()\r\n$bitmapImg.UriSource = New-Object System.Uri('${tempPath.replace(/\\\\/g, \"\\\\\\\\\")}')\r\n$bitmapImg.EndInit()\r\n\r\n$yOffset = ($pageHeight - $imgHeightWpf) / 2\r\n$xOffset = 2 / 25.4 * 96 # 2mm left margin in WPF units\r\n$rect = New-Object System.Windows.Rect($xOffset, $yOffset, $imgWidthWpf, $imgHeightWpf)\r\n$dc.DrawImage($bitmapImg, $rect)\r\n$dc.Close()\r\n\r\n$writer.Write($visual, $ticket)\r\n\r\n$xpsDoc.Close()\r\n$package.Close()\r\n$img.Dispose()\r\n\r\n$xpsDocForPrint = New-Object System.Windows.Xps.Packaging.XpsDocument($xpsPath, [System.IO.FileAccess]::Read)\r\n$seq = $xpsDocForPrint.GetFixedDocumentSequence()\r\n\r\n$xpsWriter = [System.Printing.PrintQueue]::CreateXpsDocumentWriter($queue)\r\n$xpsWriter.Write($seq, $ticket)\r\n\r\n$xpsDocForPrint.Close()\r\nRemove-Item $xpsPath -ErrorAction SilentlyContinue\r\n`;\r\n\r\n const ps = spawn(\"powershell\", [\"-Command\", psScript], { stdio: \"pipe\" });\r\n\r\n let stdout = \"\";\r\n let stderr = \"\";\r\n ps.stdout.on(\"data\", (data) => { stdout += data.toString(); });\r\n ps.stderr.on(\"data\", (data) => { stderr += data.toString(); });\r\n\r\n ps.on(\"close\", (code) => {\r\n if (code === 0) {\r\n resolve();\r\n } else {\r\n reject(new Error(`Print failed: ${stderr}`));\r\n }\r\n });\r\n\r\n ps.on(\"error\", (err) => {\r\n reject(new Error(`Failed to print: ${err.message}`));\r\n });\r\n });\r\n } finally {\r\n if (fs.existsSync(tempPath)) {\r\n fs.unlinkSync(tempPath);\r\n }\r\n }\r\n}\r\n\r\n// Main API functions\r\nexport async function render(options: PrintOptions): Promise<Buffer> {\r\n validateOptions(options);\r\n const { tape } = resolveSettings(options);\r\n return renderContent(options, tape);\r\n}\r\n\r\nexport async function print(options: PrintOptions): Promise<PrintResult> {\r\n validateOptions(options);\r\n const { tape, printer } = resolveSettings(options);\r\n const image = await renderContent(options, tape);\r\n await printBuffer(image, printer, tape);\r\n return { image };\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["api.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Brother Label Printer API\r\n * Programmatic interface for printing labels on Brother P-touch printers\r\n */\r\n\r\nimport * as fs from \"fs\";\r\nimport * as path from \"path\";\r\nimport * as os from \"os\";\r\nimport { renderHtmlFile, renderHtmlString, closeBrowser } from \"./render.js\";\r\nimport { Jimp, loadFont, measureText, measureTextHeight } from \"jimp\";\r\nimport { spawn } from \"child_process\";\r\nimport QRCode from \"qrcode\";\r\n\r\n// Types\r\nexport type TapeSize = 6 | 9 | 12 | 18 | 24;\r\nexport type Orientation = \"landscape\" | \"portrait\";\r\n\r\nexport interface PrinterConfig {\r\n defaultTape?: TapeSize;\r\n defaultPrinter?: string;\r\n}\r\n\r\nexport interface PrinterInfo {\r\n name: string;\r\n}\r\n\r\nexport interface PrintOptions {\r\n // Content (exactly one required)\r\n text?: string;\r\n html?: string;\r\n htmlPath?: string;\r\n textFile?: string;\r\n imagePath?: string;\r\n imageBuffer?: Buffer;\r\n qr?: string; // QR code data to encode\r\n\r\n // Settings\r\n tape?: TapeSize;\r\n printer?: string;\r\n orientation?: Orientation;\r\n length?: number; // explicit length in mm\r\n basePath?: string; // base path for inline HTML resources\r\n aspect?: string; // width:height ratio for HTML (e.g., \"3.5:2\")\r\n qrLabel?: string; // optional text label beside QR code\r\n}\r\n\r\nexport interface PrintResult {\r\n image: Buffer;\r\n}\r\n\r\n// Constants\r\nconst CONFIG_PATH = path.join(os.homedir(), \".brother-label.json\");\r\nconst DEFAULT_PRINTER = \"Brother PT-P710BT\";\r\nconst PRINT_DPI = 300; // High resolution for quality output\r\n\r\n// Tape sizes: height is printable area in pixels at 300 DPI\r\nconst TAPE_SIZES: Record<TapeSize, { width: number; height: number }> = {\r\n 6: { width: 1137, height: 56 }, // 3.79\" x 0.19\" @ 300 DPI\r\n 9: { width: 1137, height: 84 }, // 3.79\" x 0.28\" @ 300 DPI\r\n 12: { width: 1137, height: 113 }, // 3.79\" x 0.38\" @ 300 DPI\r\n 18: { width: 1137, height: 169 }, // 3.79\" x 0.56\" @ 300 DPI\r\n 24: { width: 1137, height: 213 }, // 3.79\" x 0.71\" @ 300 DPI\r\n};\r\n\r\n// Brother CustomMediaSize names and widths in microns\r\nconst MEDIA_OPTIONS: Record<TapeSize, { name: string; width: number }> = {\r\n 6: { name: \"CustomMediaSize257\", width: 5900 },\r\n 9: { name: \"CustomMediaSize258\", width: 9000 },\r\n 12: { name: \"CustomMediaSize259\", width: 11900 },\r\n 18: { name: \"CustomMediaSize260\", width: 18100 },\r\n 24: { name: \"CustomMediaSize261\", width: 24000 },\r\n};\r\n\r\n// Config functions\r\nexport function getConfig(): PrinterConfig {\r\n try {\r\n if (fs.existsSync(CONFIG_PATH)) {\r\n const raw = JSON.parse(fs.readFileSync(CONFIG_PATH, \"utf-8\"));\r\n // Handle legacy format where tape was stored as \"24mm\" string\r\n if (typeof raw.defaultTape === \"string\") {\r\n raw.defaultTape = parseInt(raw.defaultTape.replace(\"mm\", \"\"), 10) as TapeSize;\r\n }\r\n return raw;\r\n }\r\n } catch {\r\n // Ignore config errors\r\n }\r\n return {};\r\n}\r\n\r\nexport function setConfig(config: Partial<PrinterConfig>): void {\r\n const current = getConfig();\r\n const merged = { ...current, ...config };\r\n fs.writeFileSync(CONFIG_PATH, JSON.stringify(merged, null, 2));\r\n}\r\n\r\nexport function getConfigPath(): string {\r\n return CONFIG_PATH;\r\n}\r\n\r\n// Printer listing\r\nexport async function listPrinters(): Promise<PrinterInfo[]> {\r\n return new Promise((resolve, reject) => {\r\n const ps = spawn(\"powershell\", [\r\n \"-Command\",\r\n \"Get-Printer | Where-Object { $_.Name -like '*Brother*' -or $_.Name -like '*PT*' -or $_.Name -like '*QL*' } | Select-Object -ExpandProperty Name\"\r\n ], { stdio: \"pipe\" });\r\n\r\n let stdout = \"\";\r\n let stderr = \"\";\r\n ps.stdout.on(\"data\", (data) => { stdout += data.toString(); });\r\n ps.stderr.on(\"data\", (data) => { stderr += data.toString(); });\r\n\r\n ps.on(\"close\", (code) => {\r\n if (code !== 0) {\r\n reject(new Error(`Failed to list printers: ${stderr}`));\r\n return;\r\n }\r\n const printers = stdout.trim().split(\"\\n\")\r\n .filter(p => p.trim())\r\n .map(name => ({ name: name.trim() }));\r\n resolve(printers);\r\n });\r\n });\r\n}\r\n\r\n// Calculate HTML viewport dimensions from tape height and optional aspect ratio\r\nfunction getHtmlDimensions(tapeHeight: number, aspect?: string): { width?: number; height: number } {\r\n if (!aspect) {\r\n // Auto-detect width from content\r\n return { width: undefined, height: tapeHeight };\r\n }\r\n\r\n // Parse aspect ratio \"width:height\" or \"width/height\" (e.g., \"3.5:2\" or \"3.5/2\")\r\n const separator = aspect.includes(\"/\") ? \"/\" : \":\";\r\n const parts = aspect.split(separator);\r\n if (parts.length !== 2) {\r\n throw new Error(`Invalid aspect ratio: ${aspect}. Use format \"width:height\" or \"width/height\"`);\r\n }\r\n const aspectWidth = parseFloat(parts[0]);\r\n const aspectHeight = parseFloat(parts[1]);\r\n if (isNaN(aspectWidth) || isNaN(aspectHeight) || aspectHeight === 0) {\r\n throw new Error(`Invalid aspect ratio: ${aspect}. Use format \"width:height\" (e.g., \"3.5:2\")`);\r\n }\r\n\r\n // Scale so height fits tape, width is proportional\r\n const height = tapeHeight;\r\n const width = Math.round(tapeHeight * (aspectWidth / aspectHeight));\r\n return { width, height };\r\n}\r\n\r\n// Validation\r\nfunction validateOptions(options: PrintOptions): void {\r\n const contentFields = [\r\n options.text,\r\n options.html,\r\n options.htmlPath,\r\n options.textFile,\r\n options.imagePath,\r\n options.imageBuffer,\r\n options.qr,\r\n ].filter(f => f !== undefined);\r\n\r\n if (contentFields.length === 0) {\r\n throw new Error(\"No content provided. Specify one of: text, html, htmlPath, textFile, imagePath, imageBuffer, qr\");\r\n }\r\n if (contentFields.length > 1) {\r\n throw new Error(\"Multiple content options provided. Specify exactly one.\");\r\n }\r\n\r\n if (options.tape !== undefined && !TAPE_SIZES[options.tape]) {\r\n throw new Error(`Invalid tape size: ${options.tape}. Valid sizes: 6, 9, 12, 18, 24`);\r\n }\r\n}\r\n\r\n// Resolve effective settings from options + config + defaults\r\nfunction resolveSettings(options: PrintOptions): { tape: TapeSize; printer: string } {\r\n const config = getConfig();\r\n return {\r\n tape: options.tape ?? config.defaultTape ?? 24,\r\n printer: options.printer ?? config.defaultPrinter ?? DEFAULT_PRINTER,\r\n };\r\n}\r\n\r\n// Render text to image buffer\r\nasync function renderText(text: string, tape: TapeSize): Promise<Buffer> {\r\n const tapeSize = TAPE_SIZES[tape];\r\n const targetHeight = tapeSize.height;\r\n const lines = text.split(\"\\\\n\").join(\"\\n\");\r\n\r\n // Load largest font for quality\r\n const fontDir = path.join(path.dirname(new URL(import.meta.url).pathname).replace(/^\\/([A-Z]:)/, \"$1\"), \"node_modules/@jimp/plugin-print/fonts/open-sans\");\r\n const fontPath = path.join(fontDir, \"open-sans-128-black\", \"open-sans-128-black.fnt\");\r\n const font = await loadFont(fontPath);\r\n\r\n // Measure text\r\n const textWidth = measureText(font, lines);\r\n const textHeight = measureTextHeight(font, lines, textWidth + 100);\r\n\r\n // Create temp image for text\r\n const padding = 10;\r\n const imgWidth = textWidth + padding * 2;\r\n const imgHeight = textHeight + padding * 2;\r\n\r\n const tempImage = new Jimp({ width: imgWidth, height: imgHeight, color: 0xffffffff });\r\n tempImage.print({ font, x: padding, y: padding, text: lines });\r\n\r\n // Scale to fit tape height\r\n const scale = targetHeight / imgHeight;\r\n const finalWidth = Math.round(imgWidth * scale);\r\n const finalHeight = Math.round(imgHeight * scale);\r\n tempImage.resize({ w: finalWidth, h: finalHeight });\r\n\r\n // Create final image with padding\r\n const hPadding = Math.round(targetHeight * 0.2);\r\n const outputWidth = finalWidth + hPadding * 2;\r\n const image = new Jimp({ width: outputWidth, height: targetHeight, color: 0xffffffff });\r\n\r\n const xOffset = hPadding;\r\n const yOffset = Math.round((targetHeight - finalHeight) / 2);\r\n image.composite(tempImage, xOffset, yOffset);\r\n\r\n return image.getBuffer(\"image/png\");\r\n}\r\n\r\n// Render QR code to image buffer\r\nasync function renderQr(data: string, tape: TapeSize, labelText?: string): Promise<Buffer> {\r\n const tapeSize = TAPE_SIZES[tape];\r\n const targetHeight = tapeSize.height;\r\n const qrSize = Math.floor(targetHeight * 0.95);\r\n\r\n // Margins in pixels at PRINT_DPI (3mm left, 4mm right)\r\n const pxPerMm = PRINT_DPI / 25.4;\r\n const leftMargin = Math.round(3 * pxPerMm);\r\n const rightMargin = Math.round(4 * pxPerMm);\r\n\r\n // Generate QR code at high resolution\r\n const qrBuffer = await QRCode.toBuffer(data, {\r\n type: \"png\",\r\n width: qrSize,\r\n margin: 0,\r\n errorCorrectionLevel: \"M\",\r\n color: { dark: \"#000000\", light: \"#ffffff\" },\r\n });\r\n\r\n const qrImage = await Jimp.read(qrBuffer);\r\n\r\n if (!labelText) {\r\n // QR only\r\n const outputWidth = leftMargin + qrSize + rightMargin;\r\n const image = new Jimp({ width: outputWidth, height: targetHeight, color: 0xffffffff });\r\n const yOffset = Math.floor((targetHeight - qrSize) / 2);\r\n image.composite(qrImage, leftMargin, yOffset);\r\n return image.getBuffer(\"image/png\");\r\n }\r\n\r\n // QR + text label\r\n const fontDir = path.join(path.dirname(new URL(import.meta.url).pathname).replace(/^\\/([A-Z]:)/, \"$1\"), \"node_modules/@jimp/plugin-print/fonts/open-sans\");\r\n const fontPath = path.join(fontDir, \"open-sans-64-black\", \"open-sans-64-black.fnt\");\r\n const font = await loadFont(fontPath);\r\n\r\n const textWidth = measureText(font, labelText);\r\n const textHeight = measureTextHeight(font, labelText, textWidth + 50);\r\n\r\n // Scale text to fit beside QR\r\n const maxTextHeight = targetHeight * 0.8;\r\n const textScale = Math.min(1, maxTextHeight / textHeight);\r\n const scaledTextWidth = Math.round(textWidth * textScale);\r\n const scaledTextHeight = Math.round(textHeight * textScale);\r\n\r\n // Create text image\r\n const textImg = new Jimp({ width: textWidth + 20, height: textHeight + 20, color: 0xffffffff });\r\n textImg.print({ font, x: 10, y: 10, text: labelText });\r\n if (textScale < 1) {\r\n textImg.resize({ w: scaledTextWidth, h: scaledTextHeight });\r\n }\r\n\r\n // Compose: QR on left, text on right\r\n const gap = Math.floor(targetHeight * 0.15);\r\n const outputWidth = leftMargin + qrSize + gap + scaledTextWidth + rightMargin;\r\n const image = new Jimp({ width: outputWidth, height: targetHeight, color: 0xffffffff });\r\n\r\n const qrY = Math.floor((targetHeight - qrSize) / 2);\r\n image.composite(qrImage, leftMargin, qrY);\r\n\r\n const textY = Math.floor((targetHeight - scaledTextHeight) / 2);\r\n image.composite(textImg, leftMargin + qrSize + gap, textY);\r\n\r\n return image.getBuffer(\"image/png\");\r\n}\r\n\r\n// Render content to image buffer\r\nasync function renderContent(options: PrintOptions, tape: TapeSize): Promise<Buffer> {\r\n const tapeSize = TAPE_SIZES[tape];\r\n\r\n if (options.text !== undefined) {\r\n return renderText(options.text, tape);\r\n }\r\n\r\n if (options.textFile !== undefined) {\r\n const text = fs.readFileSync(options.textFile, \"utf-8\");\r\n return renderText(text, tape);\r\n }\r\n\r\n if (options.html !== undefined) {\r\n const { width, height } = getHtmlDimensions(tapeSize.height, options.aspect);\r\n const buffer = await renderHtmlString(options.html, { width, height, tapeMm: tape }, options.basePath);\r\n await closeBrowser();\r\n return buffer;\r\n }\r\n\r\n if (options.htmlPath !== undefined) {\r\n const { width, height } = getHtmlDimensions(tapeSize.height, options.aspect);\r\n const buffer = await renderHtmlFile(options.htmlPath, { width, height, tapeMm: tape });\r\n await closeBrowser();\r\n return buffer;\r\n }\r\n\r\n if (options.imagePath !== undefined) {\r\n return fs.readFileSync(options.imagePath);\r\n }\r\n\r\n if (options.imageBuffer !== undefined) {\r\n return options.imageBuffer;\r\n }\r\n\r\n if (options.qr !== undefined) {\r\n return renderQr(options.qr, tape, options.qrLabel);\r\n }\r\n\r\n throw new Error(\"No content to render\");\r\n}\r\n\r\n// Print single image buffer to printer\r\nasync function printBuffer(imageBuffer: Buffer, printer: string, tape: TapeSize): Promise<void> {\r\n const media = MEDIA_OPTIONS[tape];\r\n\r\n const tempPath = path.join(os.tmpdir(), `label-${Date.now()}.png`);\r\n fs.writeFileSync(tempPath, imageBuffer);\r\n\r\n try {\r\n await new Promise<void>((resolve, reject) => {\r\n const psScript = `\r\nAdd-Type -AssemblyName System.Drawing\r\nAdd-Type -AssemblyName System.Printing\r\nAdd-Type -AssemblyName ReachFramework\r\nAdd-Type -AssemblyName PresentationCore\r\n\r\n$img = [System.Drawing.Image]::FromFile('${tempPath.replace(/\\\\/g, \"\\\\\\\\\")}')\r\n\r\n$DPI = ${PRINT_DPI}\r\n$MICRONS_PER_INCH = 25400\r\n\r\n$labelLengthMicrons = [int]($img.Width / $DPI * $MICRONS_PER_INCH) + 3000 # +2mm offset +1mm buffer\r\n$tapeWidthMicrons = ${media.width}\r\n\r\n$imgWidthWpf = $img.Width / $DPI * 96\r\n$imgHeightWpf = $img.Height / $DPI * 96\r\n\r\n$ticketXml = @\"\r\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<psf:PrintTicket xmlns:psf=\"http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework\"\r\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" version=\"1\"\r\n xmlns:psk=\"http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords\"\r\n xmlns:ns0001=\"http://schemas.brother.info/mfc/printing/2006/11/printschemakeywords\">\r\n <psf:Feature name=\"psk:PageMediaSize\">\r\n <psf:Option name=\"ns0001:${media.name}\">\r\n <psf:ScoredProperty name=\"psk:MediaSizeWidth\">\r\n <psf:Value xsi:type=\"xsd:integer\">${media.width}</psf:Value>\r\n </psf:ScoredProperty>\r\n <psf:ScoredProperty name=\"psk:MediaSizeHeight\">\r\n <psf:ParameterRef name=\"psk:PageMediaSizeMediaSizeHeight\" />\r\n </psf:ScoredProperty>\r\n </psf:Option>\r\n </psf:Feature>\r\n <psf:ParameterInit name=\"psk:PageMediaSizeMediaSizeHeight\">\r\n <psf:Value xsi:type=\"xsd:integer\">$labelLengthMicrons</psf:Value>\r\n </psf:ParameterInit>\r\n <psf:Feature name=\"psk:PageOrientation\">\r\n <psf:Option name=\"psk:Landscape\" />\r\n </psf:Feature>\r\n <psf:Feature name=\"ns0001:PageRollFeedToEndOfSheet\">\r\n <psf:Option name=\"ns0001:FeedToImageEdge\" />\r\n </psf:Feature>\r\n <psf:Feature name=\"psk:PageMediaType\">\r\n <psf:Option name=\"psk:Label\" />\r\n </psf:Feature>\r\n <psf:Feature name=\"ns0001:JobRollCutAtEndOfJob\">\r\n <psf:Option name=\"ns0001:Cut\" />\r\n </psf:Feature>\r\n</psf:PrintTicket>\r\n\"@\r\n\r\n$xmlBytes = [System.Text.Encoding]::UTF8.GetBytes($ticketXml)\r\n$memStream = New-Object System.IO.MemoryStream(,$xmlBytes)\r\n$ticket = New-Object System.Printing.PrintTicket($memStream)\r\n\r\n$server = New-Object System.Printing.LocalPrintServer\r\n$queue = $server.GetPrintQueue('${printer}')\r\n\r\n$xpsPath = [System.IO.Path]::GetTempFileName() + \".xps\"\r\n\r\n$pageWidth = $labelLengthMicrons / $MICRONS_PER_INCH * 96\r\n$pageHeight = $tapeWidthMicrons / $MICRONS_PER_INCH * 96\r\n\r\n$package = [System.IO.Packaging.Package]::Open($xpsPath, [System.IO.FileMode]::Create)\r\n$xpsDoc = New-Object System.Windows.Xps.Packaging.XpsDocument($package)\r\n$writer = [System.Windows.Xps.Packaging.XpsDocument]::CreateXpsDocumentWriter($xpsDoc)\r\n\r\n$visual = New-Object System.Windows.Media.DrawingVisual\r\n$dc = $visual.RenderOpen()\r\n\r\n$bitmapImg = New-Object System.Windows.Media.Imaging.BitmapImage\r\n$bitmapImg.BeginInit()\r\n$bitmapImg.UriSource = New-Object System.Uri('${tempPath.replace(/\\\\/g, \"\\\\\\\\\")}')\r\n$bitmapImg.EndInit()\r\n\r\n$yOffset = ($pageHeight - $imgHeightWpf) / 2\r\n$xOffset = 2 / 25.4 * 96 # 2mm left margin in WPF units\r\n$rect = New-Object System.Windows.Rect($xOffset, $yOffset, $imgWidthWpf, $imgHeightWpf)\r\n$dc.DrawImage($bitmapImg, $rect)\r\n$dc.Close()\r\n\r\n$writer.Write($visual, $ticket)\r\n\r\n$xpsDoc.Close()\r\n$package.Close()\r\n$img.Dispose()\r\n\r\n$xpsDocForPrint = New-Object System.Windows.Xps.Packaging.XpsDocument($xpsPath, [System.IO.FileAccess]::Read)\r\n$seq = $xpsDocForPrint.GetFixedDocumentSequence()\r\n\r\n$xpsWriter = [System.Printing.PrintQueue]::CreateXpsDocumentWriter($queue)\r\n$xpsWriter.Write($seq, $ticket)\r\n\r\n$xpsDocForPrint.Close()\r\nRemove-Item $xpsPath -ErrorAction SilentlyContinue\r\n`;\r\n\r\n const ps = spawn(\"powershell\", [\"-Command\", psScript], { stdio: \"pipe\" });\r\n\r\n let stdout = \"\";\r\n let stderr = \"\";\r\n ps.stdout.on(\"data\", (data) => { stdout += data.toString(); });\r\n ps.stderr.on(\"data\", (data) => { stderr += data.toString(); });\r\n\r\n ps.on(\"close\", (code) => {\r\n if (code === 0) {\r\n resolve();\r\n } else {\r\n reject(new Error(`Print failed: ${stderr}`));\r\n }\r\n });\r\n\r\n ps.on(\"error\", (err) => {\r\n reject(new Error(`Failed to print: ${err.message}`));\r\n });\r\n });\r\n } finally {\r\n if (fs.existsSync(tempPath)) {\r\n fs.unlinkSync(tempPath);\r\n }\r\n }\r\n}\r\n\r\n// Main API functions\r\nexport async function render(options: PrintOptions): Promise<Buffer> {\r\n validateOptions(options);\r\n const { tape } = resolveSettings(options);\r\n return renderContent(options, tape);\r\n}\r\n\r\nexport async function print(options: PrintOptions): Promise<PrintResult> {\r\n validateOptions(options);\r\n const { tape, printer } = resolveSettings(options);\r\n const image = await renderContent(options, tape);\r\n await printBuffer(image, printer, tape);\r\n return { image };\r\n}\r\n"]}
|
package/api.ts
CHANGED
|
@@ -385,19 +385,9 @@ $ticketXml = @"
|
|
|
385
385
|
<psf:Feature name="psk:PageMediaType">
|
|
386
386
|
<psf:Option name="psk:Label" />
|
|
387
387
|
</psf:Feature>
|
|
388
|
-
<psf:Feature name="
|
|
389
|
-
<psf:Option name="
|
|
388
|
+
<psf:Feature name="ns0001:JobRollCutAtEndOfJob">
|
|
389
|
+
<psf:Option name="ns0001:Cut" />
|
|
390
390
|
</psf:Feature>
|
|
391
|
-
<psf:Feature name="ns0001:JobRollCutSheet">
|
|
392
|
-
<psf:Option name="ns0001:CutSheet">
|
|
393
|
-
<psf:ScoredProperty name="ns0001:CutSheetCount">
|
|
394
|
-
<psf:ParameterRef name="ns0001:JobCutSheetCount" />
|
|
395
|
-
</psf:ScoredProperty>
|
|
396
|
-
</psf:Option>
|
|
397
|
-
</psf:Feature>
|
|
398
|
-
<psf:ParameterInit name="ns0001:JobCutSheetCount">
|
|
399
|
-
<psf:Value xsi:type="xsd:integer">1</psf:Value>
|
|
400
|
-
</psf:ParameterInit>
|
|
401
391
|
</psf:PrintTicket>
|
|
402
392
|
"@
|
|
403
393
|
|