@bobfrankston/brother-label 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,193 @@
1
+ # @bobfrankston/brother-label
2
+
3
+ Print labels to Brother P-touch label printers from Node.js. Supports text, HTML, images, and QR codes.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @bobfrankston/brother-label
9
+ ```
10
+
11
+ ## Command Line Usage
12
+
13
+ ### Print text
14
+ ```bash
15
+ brother-print print "Hello World"
16
+ brother-print print "Line 1\\nLine 2" # Multi-line
17
+ ```
18
+
19
+ ### Print QR code
20
+ ```bash
21
+ brother-print qr "https://example.com"
22
+ brother-print qr "https://example.com" -l "My Site" # With text label
23
+ brother-print qr "any data" -o qr.png # Save to file
24
+ ```
25
+
26
+ ### Print HTML
27
+ ```bash
28
+ brother-print html label.html
29
+ ```
30
+
31
+ #### Inline QR codes in HTML
32
+ Use `<img qr="data">` to embed QR codes directly in HTML - they're converted to base64 at render time:
33
+ ```html
34
+ <img qr="https://example.com" style="width:10mm; height:10mm">
35
+ <img qr="any data here" class="my-qr">
36
+ ```
37
+
38
+ ### Print image
39
+ ```bash
40
+ brother-print image photo.png
41
+ ```
42
+
43
+ ### Preview (save without printing)
44
+ ```bash
45
+ brother-print preview "Test Label" -o preview.png
46
+ ```
47
+
48
+ ### Configuration
49
+ ```bash
50
+ brother-print config --show # Show current config
51
+ brother-print config -t 12mm # Set default tape size
52
+ brother-print config -p "Brother PT-P710BT" # Set default printer
53
+ brother-print list # List Brother printers
54
+ ```
55
+
56
+ ### Options
57
+ | Option | Description |
58
+ |--------|-------------|
59
+ | `-p, --printer <name>` | Printer name |
60
+ | `-t, --tape <size>` | Tape size: 6mm, 9mm, 12mm, 18mm, 24mm, or 'auto' |
61
+ | `-l, --label <text>` | Text label beside QR code (qr command only) |
62
+ | `-o, --output <file>` | Save to file instead of printing |
63
+
64
+ ## API Usage
65
+
66
+ ### Print text
67
+ ```typescript
68
+ import { print } from "@bobfrankston/brother-label";
69
+
70
+ await print({ text: "Hello World" });
71
+ await print({ text: "Hello", tape: 12 }); // 12mm tape
72
+ ```
73
+
74
+ ### Print QR code
75
+ ```typescript
76
+ import { print, render } from "@bobfrankston/brother-label";
77
+
78
+ // Print QR code
79
+ await print({ qr: "https://example.com" });
80
+
81
+ // QR code with text label
82
+ await print({ qr: "https://example.com", qrLabel: "My Site" });
83
+
84
+ // Render to buffer without printing
85
+ const buffer = await render({ qr: "https://example.com" });
86
+ ```
87
+
88
+ ### Print HTML
89
+ ```typescript
90
+ // From file
91
+ await print({ htmlPath: "label.html" });
92
+
93
+ // Inline HTML
94
+ await print({
95
+ html: "<div style='font-size:24px'>Hello</div>",
96
+ basePath: __dirname // For resolving relative resources
97
+ });
98
+
99
+ // With aspect ratio
100
+ await print({ htmlPath: "label.html", aspect: "4:1" });
101
+
102
+ // HTML with inline QR codes - <img qr="..."> auto-converted to base64
103
+ await print({
104
+ html: `<img qr="https://example.com" style="width:10mm">`,
105
+ });
106
+ ```
107
+
108
+ ### Print image
109
+ ```typescript
110
+ // From file
111
+ await print({ imagePath: "photo.png" });
112
+
113
+ // From buffer
114
+ await print({ imageBuffer: fs.readFileSync("photo.png") });
115
+ ```
116
+
117
+ ### Configuration
118
+ ```typescript
119
+ import { getConfig, setConfig, listPrinters } from "@bobfrankston/brother-label";
120
+
121
+ // Get current config
122
+ const config = getConfig();
123
+ console.log(config.defaultTape); // 12
124
+ console.log(config.defaultPrinter); // "Brother PT-P710BT"
125
+
126
+ // Set defaults
127
+ setConfig({ defaultTape: 24, defaultPrinter: "Brother PT-P710BT" });
128
+
129
+ // List printers
130
+ const printers = await listPrinters();
131
+ printers.forEach(p => console.log(p.name));
132
+ ```
133
+
134
+ ### Render without printing
135
+ ```typescript
136
+ import { render } from "@bobfrankston/brother-label";
137
+
138
+ const buffer = await render({ text: "Hello" });
139
+ fs.writeFileSync("label.png", buffer);
140
+ ```
141
+
142
+ ## API Reference
143
+
144
+ ### Types
145
+
146
+ ```typescript
147
+ type TapeSize = 6 | 9 | 12 | 18 | 24;
148
+
149
+ interface PrintOptions {
150
+ // Content (exactly one required)
151
+ text?: string; // Plain text
152
+ html?: string; // Inline HTML
153
+ htmlPath?: string; // Path to HTML file
154
+ textFile?: string; // Path to text file
155
+ imagePath?: string; // Path to image file
156
+ imageBuffer?: Buffer; // Image buffer
157
+ qr?: string; // QR code data
158
+
159
+ // Settings
160
+ tape?: TapeSize; // Tape size in mm
161
+ printer?: string; // Printer name
162
+ basePath?: string; // Base path for HTML resources
163
+ aspect?: string; // Aspect ratio for HTML (e.g., "4:1")
164
+ qrLabel?: string; // Text label beside QR code
165
+ }
166
+
167
+ interface PrintResult {
168
+ image: Buffer; // The rendered image
169
+ }
170
+ ```
171
+
172
+ ### Functions
173
+
174
+ | Function | Description |
175
+ |----------|-------------|
176
+ | `print(options)` | Render and print a label |
177
+ | `render(options)` | Render label to PNG buffer |
178
+ | `getConfig()` | Get current configuration |
179
+ | `setConfig(config)` | Set default tape/printer |
180
+ | `getConfigPath()` | Get config file path |
181
+ | `listPrinters()` | List Brother printers |
182
+
183
+ ## Supported Printers
184
+
185
+ - Brother PT-P710BT (tested)
186
+ - Other Brother P-touch printers (should work)
187
+ - Brother QL series (untested)
188
+
189
+ ## Requirements
190
+
191
+ - Windows (uses Windows printing APIs)
192
+ - Node.js 20+
193
+ - Puppeteer (for HTML rendering)
package/api.d.ts ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Brother Label Printer API
3
+ * Programmatic interface for printing labels on Brother P-touch printers
4
+ */
5
+ export type TapeSize = 6 | 9 | 12 | 18 | 24;
6
+ export type Orientation = "landscape" | "portrait";
7
+ export interface PrinterConfig {
8
+ defaultTape?: TapeSize;
9
+ defaultPrinter?: string;
10
+ }
11
+ export interface PrinterInfo {
12
+ name: string;
13
+ }
14
+ export interface PrintOptions {
15
+ text?: string;
16
+ html?: string;
17
+ htmlPath?: string;
18
+ textFile?: string;
19
+ imagePath?: string;
20
+ imageBuffer?: Buffer;
21
+ qr?: string;
22
+ tape?: TapeSize;
23
+ printer?: string;
24
+ orientation?: Orientation;
25
+ length?: number;
26
+ basePath?: string;
27
+ aspect?: string;
28
+ qrLabel?: string;
29
+ }
30
+ export interface PrintResult {
31
+ image: Buffer;
32
+ }
33
+ export declare function getConfig(): PrinterConfig;
34
+ export declare function setConfig(config: Partial<PrinterConfig>): void;
35
+ export declare function getConfigPath(): string;
36
+ export declare function listPrinters(): Promise<PrinterInfo[]>;
37
+ export declare function render(options: PrintOptions): Promise<Buffer>;
38
+ export declare function print(options: PrintOptions): Promise<PrintResult>;
39
+ //# sourceMappingURL=api.d.ts.map
package/api.d.ts.map ADDED
@@ -0,0 +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;AA+VD,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 ADDED
@@ -0,0 +1,398 @@
1
+ /**
2
+ * Brother Label Printer API
3
+ * Programmatic interface for printing labels on Brother P-touch printers
4
+ */
5
+ import * as fs from "fs";
6
+ import * as path from "path";
7
+ import * as os from "os";
8
+ import { renderHtmlFile, renderHtmlString, closeBrowser } from "./render.js";
9
+ import { Jimp, loadFont, measureText, measureTextHeight } from "jimp";
10
+ import { spawn } from "child_process";
11
+ import QRCode from "qrcode";
12
+ // Constants
13
+ const CONFIG_PATH = path.join(os.homedir(), ".brother-label.json");
14
+ const DEFAULT_PRINTER = "Brother PT-P710BT";
15
+ const PRINT_DPI = 300; // High resolution for quality output
16
+ // Tape sizes: height is printable area in pixels at 300 DPI
17
+ const TAPE_SIZES = {
18
+ 6: { width: 1137, height: 56 }, // 3.79" x 0.19" @ 300 DPI
19
+ 9: { width: 1137, height: 84 }, // 3.79" x 0.28" @ 300 DPI
20
+ 12: { width: 1137, height: 113 }, // 3.79" x 0.38" @ 300 DPI
21
+ 18: { width: 1137, height: 169 }, // 3.79" x 0.56" @ 300 DPI
22
+ 24: { width: 1137, height: 213 }, // 3.79" x 0.71" @ 300 DPI
23
+ };
24
+ // Brother CustomMediaSize names and widths in microns
25
+ const MEDIA_OPTIONS = {
26
+ 6: { name: "CustomMediaSize257", width: 5900 },
27
+ 9: { name: "CustomMediaSize258", width: 9000 },
28
+ 12: { name: "CustomMediaSize259", width: 11900 },
29
+ 18: { name: "CustomMediaSize260", width: 18100 },
30
+ 24: { name: "CustomMediaSize261", width: 24000 },
31
+ };
32
+ // Config functions
33
+ export function getConfig() {
34
+ try {
35
+ if (fs.existsSync(CONFIG_PATH)) {
36
+ const raw = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
37
+ // Handle legacy format where tape was stored as "24mm" string
38
+ if (typeof raw.defaultTape === "string") {
39
+ raw.defaultTape = parseInt(raw.defaultTape.replace("mm", ""), 10);
40
+ }
41
+ return raw;
42
+ }
43
+ }
44
+ catch {
45
+ // Ignore config errors
46
+ }
47
+ return {};
48
+ }
49
+ export function setConfig(config) {
50
+ const current = getConfig();
51
+ const merged = { ...current, ...config };
52
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(merged, null, 2));
53
+ }
54
+ export function getConfigPath() {
55
+ return CONFIG_PATH;
56
+ }
57
+ // Printer listing
58
+ export async function listPrinters() {
59
+ return new Promise((resolve, reject) => {
60
+ const ps = spawn("powershell", [
61
+ "-Command",
62
+ "Get-Printer | Where-Object { $_.Name -like '*Brother*' -or $_.Name -like '*PT*' -or $_.Name -like '*QL*' } | Select-Object -ExpandProperty Name"
63
+ ], { stdio: "pipe" });
64
+ let stdout = "";
65
+ let stderr = "";
66
+ ps.stdout.on("data", (data) => { stdout += data.toString(); });
67
+ ps.stderr.on("data", (data) => { stderr += data.toString(); });
68
+ ps.on("close", (code) => {
69
+ if (code !== 0) {
70
+ reject(new Error(`Failed to list printers: ${stderr}`));
71
+ return;
72
+ }
73
+ const printers = stdout.trim().split("\n")
74
+ .filter(p => p.trim())
75
+ .map(name => ({ name: name.trim() }));
76
+ resolve(printers);
77
+ });
78
+ });
79
+ }
80
+ // Calculate HTML viewport dimensions from tape height and optional aspect ratio
81
+ function getHtmlDimensions(tapeHeight, aspect) {
82
+ if (!aspect) {
83
+ // Default: square viewport
84
+ return { width: tapeHeight, height: tapeHeight };
85
+ }
86
+ // Parse aspect ratio "width:height" or "width/height" (e.g., "3.5:2" or "3.5/2")
87
+ const separator = aspect.includes("/") ? "/" : ":";
88
+ const parts = aspect.split(separator);
89
+ if (parts.length !== 2) {
90
+ throw new Error(`Invalid aspect ratio: ${aspect}. Use format "width:height" or "width/height"`);
91
+ }
92
+ const aspectWidth = parseFloat(parts[0]);
93
+ const aspectHeight = parseFloat(parts[1]);
94
+ if (isNaN(aspectWidth) || isNaN(aspectHeight) || aspectHeight === 0) {
95
+ throw new Error(`Invalid aspect ratio: ${aspect}. Use format "width:height" (e.g., "3.5:2")`);
96
+ }
97
+ // Scale so height fits tape, width is proportional
98
+ const height = tapeHeight;
99
+ const width = Math.round(tapeHeight * (aspectWidth / aspectHeight));
100
+ return { width, height };
101
+ }
102
+ // Validation
103
+ function validateOptions(options) {
104
+ const contentFields = [
105
+ options.text,
106
+ options.html,
107
+ options.htmlPath,
108
+ options.textFile,
109
+ options.imagePath,
110
+ options.imageBuffer,
111
+ options.qr,
112
+ ].filter(f => f !== undefined);
113
+ if (contentFields.length === 0) {
114
+ throw new Error("No content provided. Specify one of: text, html, htmlPath, textFile, imagePath, imageBuffer, qr");
115
+ }
116
+ if (contentFields.length > 1) {
117
+ throw new Error("Multiple content options provided. Specify exactly one.");
118
+ }
119
+ if (options.tape !== undefined && !TAPE_SIZES[options.tape]) {
120
+ throw new Error(`Invalid tape size: ${options.tape}. Valid sizes: 6, 9, 12, 18, 24`);
121
+ }
122
+ }
123
+ // Resolve effective settings from options + config + defaults
124
+ function resolveSettings(options) {
125
+ const config = getConfig();
126
+ return {
127
+ tape: options.tape ?? config.defaultTape ?? 24,
128
+ printer: options.printer ?? config.defaultPrinter ?? DEFAULT_PRINTER,
129
+ };
130
+ }
131
+ // Render text to image buffer
132
+ async function renderText(text, tape) {
133
+ const tapeSize = TAPE_SIZES[tape];
134
+ const targetHeight = tapeSize.height;
135
+ const lines = text.split("\\n").join("\n");
136
+ // Load largest font for quality
137
+ const fontDir = path.join(path.dirname(new URL(import.meta.url).pathname).replace(/^\/([A-Z]:)/, "$1"), "node_modules/@jimp/plugin-print/fonts/open-sans");
138
+ const fontPath = path.join(fontDir, "open-sans-128-black", "open-sans-128-black.fnt");
139
+ const font = await loadFont(fontPath);
140
+ // Measure text
141
+ const textWidth = measureText(font, lines);
142
+ const textHeight = measureTextHeight(font, lines, textWidth + 100);
143
+ // Create temp image for text
144
+ const padding = 10;
145
+ const imgWidth = textWidth + padding * 2;
146
+ const imgHeight = textHeight + padding * 2;
147
+ const tempImage = new Jimp({ width: imgWidth, height: imgHeight, color: 0xffffffff });
148
+ tempImage.print({ font, x: padding, y: padding, text: lines });
149
+ // Scale to fit tape height
150
+ const scale = targetHeight / imgHeight;
151
+ const finalWidth = Math.round(imgWidth * scale);
152
+ const finalHeight = Math.round(imgHeight * scale);
153
+ tempImage.resize({ w: finalWidth, h: finalHeight });
154
+ // Create final image with padding
155
+ const hPadding = Math.round(targetHeight * 0.2);
156
+ const outputWidth = finalWidth + hPadding * 2;
157
+ const image = new Jimp({ width: outputWidth, height: targetHeight, color: 0xffffffff });
158
+ const xOffset = hPadding;
159
+ const yOffset = Math.round((targetHeight - finalHeight) / 2);
160
+ image.composite(tempImage, xOffset, yOffset);
161
+ return image.getBuffer("image/png");
162
+ }
163
+ // Render QR code to image buffer
164
+ async function renderQr(data, tape, labelText) {
165
+ const tapeSize = TAPE_SIZES[tape];
166
+ const targetHeight = tapeSize.height;
167
+ const qrSize = Math.floor(targetHeight * 0.95);
168
+ // Margins in pixels at PRINT_DPI (3mm left, 4mm right)
169
+ const pxPerMm = PRINT_DPI / 25.4;
170
+ const leftMargin = Math.round(3 * pxPerMm);
171
+ const rightMargin = Math.round(4 * pxPerMm);
172
+ // Generate QR code at high resolution
173
+ const qrBuffer = await QRCode.toBuffer(data, {
174
+ type: "png",
175
+ width: qrSize,
176
+ margin: 0,
177
+ errorCorrectionLevel: "M",
178
+ color: { dark: "#000000", light: "#ffffff" },
179
+ });
180
+ const qrImage = await Jimp.read(qrBuffer);
181
+ if (!labelText) {
182
+ // QR only
183
+ const outputWidth = leftMargin + qrSize + rightMargin;
184
+ const image = new Jimp({ width: outputWidth, height: targetHeight, color: 0xffffffff });
185
+ const yOffset = Math.floor((targetHeight - qrSize) / 2);
186
+ image.composite(qrImage, leftMargin, yOffset);
187
+ return image.getBuffer("image/png");
188
+ }
189
+ // QR + text label
190
+ const fontDir = path.join(path.dirname(new URL(import.meta.url).pathname).replace(/^\/([A-Z]:)/, "$1"), "node_modules/@jimp/plugin-print/fonts/open-sans");
191
+ const fontPath = path.join(fontDir, "open-sans-64-black", "open-sans-64-black.fnt");
192
+ const font = await loadFont(fontPath);
193
+ const textWidth = measureText(font, labelText);
194
+ const textHeight = measureTextHeight(font, labelText, textWidth + 50);
195
+ // Scale text to fit beside QR
196
+ const maxTextHeight = targetHeight * 0.8;
197
+ const textScale = Math.min(1, maxTextHeight / textHeight);
198
+ const scaledTextWidth = Math.round(textWidth * textScale);
199
+ const scaledTextHeight = Math.round(textHeight * textScale);
200
+ // Create text image
201
+ const textImg = new Jimp({ width: textWidth + 20, height: textHeight + 20, color: 0xffffffff });
202
+ textImg.print({ font, x: 10, y: 10, text: labelText });
203
+ if (textScale < 1) {
204
+ textImg.resize({ w: scaledTextWidth, h: scaledTextHeight });
205
+ }
206
+ // Compose: QR on left, text on right
207
+ const gap = Math.floor(targetHeight * 0.15);
208
+ const outputWidth = leftMargin + qrSize + gap + scaledTextWidth + rightMargin;
209
+ const image = new Jimp({ width: outputWidth, height: targetHeight, color: 0xffffffff });
210
+ const qrY = Math.floor((targetHeight - qrSize) / 2);
211
+ image.composite(qrImage, leftMargin, qrY);
212
+ const textY = Math.floor((targetHeight - scaledTextHeight) / 2);
213
+ image.composite(textImg, leftMargin + qrSize + gap, textY);
214
+ return image.getBuffer("image/png");
215
+ }
216
+ // Render content to image buffer
217
+ async function renderContent(options, tape) {
218
+ const tapeSize = TAPE_SIZES[tape];
219
+ if (options.text !== undefined) {
220
+ return renderText(options.text, tape);
221
+ }
222
+ if (options.textFile !== undefined) {
223
+ const text = fs.readFileSync(options.textFile, "utf-8");
224
+ return renderText(text, tape);
225
+ }
226
+ if (options.html !== undefined) {
227
+ const { width, height } = getHtmlDimensions(tapeSize.height, options.aspect);
228
+ const buffer = await renderHtmlString(options.html, { width, height }, options.basePath);
229
+ await closeBrowser();
230
+ return buffer;
231
+ }
232
+ if (options.htmlPath !== undefined) {
233
+ const { width, height } = getHtmlDimensions(tapeSize.height, options.aspect);
234
+ const buffer = await renderHtmlFile(options.htmlPath, { width, height });
235
+ await closeBrowser();
236
+ return buffer;
237
+ }
238
+ if (options.imagePath !== undefined) {
239
+ return fs.readFileSync(options.imagePath);
240
+ }
241
+ if (options.imageBuffer !== undefined) {
242
+ return options.imageBuffer;
243
+ }
244
+ if (options.qr !== undefined) {
245
+ return renderQr(options.qr, tape, options.qrLabel);
246
+ }
247
+ throw new Error("No content to render");
248
+ }
249
+ // Print single image buffer to printer
250
+ async function printBuffer(imageBuffer, printer, tape) {
251
+ const media = MEDIA_OPTIONS[tape];
252
+ const tempPath = path.join(os.tmpdir(), `label-${Date.now()}.png`);
253
+ fs.writeFileSync(tempPath, imageBuffer);
254
+ try {
255
+ await new Promise((resolve, reject) => {
256
+ const psScript = `
257
+ Add-Type -AssemblyName System.Drawing
258
+ Add-Type -AssemblyName System.Printing
259
+ Add-Type -AssemblyName ReachFramework
260
+ Add-Type -AssemblyName PresentationCore
261
+
262
+ $img = [System.Drawing.Image]::FromFile('${tempPath.replace(/\\/g, "\\\\")}')
263
+
264
+ $DPI = ${PRINT_DPI}
265
+ $MICRONS_PER_INCH = 25400
266
+
267
+ $labelLengthMicrons = [int]($img.Width / $DPI * $MICRONS_PER_INCH) + 1000
268
+ $tapeWidthMicrons = ${media.width}
269
+
270
+ $imgWidthWpf = $img.Width / $DPI * 96
271
+ $imgHeightWpf = $img.Height / $DPI * 96
272
+
273
+ $ticketXml = @"
274
+ <?xml version="1.0" encoding="UTF-8"?>
275
+ <psf:PrintTicket xmlns:psf="http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework"
276
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="1"
277
+ xmlns:psk="http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords"
278
+ xmlns:ns0001="http://schemas.brother.info/mfc/printing/2006/11/printschemakeywords">
279
+ <psf:Feature name="psk:PageMediaSize">
280
+ <psf:Option name="ns0001:${media.name}">
281
+ <psf:ScoredProperty name="psk:MediaSizeWidth">
282
+ <psf:Value xsi:type="xsd:integer">${media.width}</psf:Value>
283
+ </psf:ScoredProperty>
284
+ <psf:ScoredProperty name="psk:MediaSizeHeight">
285
+ <psf:ParameterRef name="psk:PageMediaSizeMediaSizeHeight" />
286
+ </psf:ScoredProperty>
287
+ </psf:Option>
288
+ </psf:Feature>
289
+ <psf:ParameterInit name="psk:PageMediaSizeMediaSizeHeight">
290
+ <psf:Value xsi:type="xsd:integer">$labelLengthMicrons</psf:Value>
291
+ </psf:ParameterInit>
292
+ <psf:Feature name="psk:PageOrientation">
293
+ <psf:Option name="psk:Landscape" />
294
+ </psf:Feature>
295
+ <psf:Feature name="ns0001:PageRollFeedToEndOfSheet">
296
+ <psf:Option name="ns0001:FeedToImageEdge" />
297
+ </psf:Feature>
298
+ <psf:Feature name="psk:PageMediaType">
299
+ <psf:Option name="psk:Label" />
300
+ </psf:Feature>
301
+ <psf:Feature name="psk:JobRollCutAtEndOfJob">
302
+ <psf:Option name="psk:CutSheetAtStandardMediaSize" />
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
+ </psf:PrintTicket>
315
+ "@
316
+
317
+ $xmlBytes = [System.Text.Encoding]::UTF8.GetBytes($ticketXml)
318
+ $memStream = New-Object System.IO.MemoryStream(,$xmlBytes)
319
+ $ticket = New-Object System.Printing.PrintTicket($memStream)
320
+
321
+ $server = New-Object System.Printing.LocalPrintServer
322
+ $queue = $server.GetPrintQueue('${printer}')
323
+
324
+ $xpsPath = [System.IO.Path]::GetTempFileName() + ".xps"
325
+
326
+ $pageWidth = $labelLengthMicrons / $MICRONS_PER_INCH * 96
327
+ $pageHeight = $tapeWidthMicrons / $MICRONS_PER_INCH * 96
328
+
329
+ $package = [System.IO.Packaging.Package]::Open($xpsPath, [System.IO.FileMode]::Create)
330
+ $xpsDoc = New-Object System.Windows.Xps.Packaging.XpsDocument($package)
331
+ $writer = [System.Windows.Xps.Packaging.XpsDocument]::CreateXpsDocumentWriter($xpsDoc)
332
+
333
+ $visual = New-Object System.Windows.Media.DrawingVisual
334
+ $dc = $visual.RenderOpen()
335
+
336
+ $bitmapImg = New-Object System.Windows.Media.Imaging.BitmapImage
337
+ $bitmapImg.BeginInit()
338
+ $bitmapImg.UriSource = New-Object System.Uri('${tempPath.replace(/\\/g, "\\\\")}')
339
+ $bitmapImg.EndInit()
340
+
341
+ $yOffset = ($pageHeight - $imgHeightWpf) / 2
342
+ $rect = New-Object System.Windows.Rect(0, $yOffset, $imgWidthWpf, $imgHeightWpf)
343
+ $dc.DrawImage($bitmapImg, $rect)
344
+ $dc.Close()
345
+
346
+ $writer.Write($visual, $ticket)
347
+
348
+ $xpsDoc.Close()
349
+ $package.Close()
350
+ $img.Dispose()
351
+
352
+ $xpsDocForPrint = New-Object System.Windows.Xps.Packaging.XpsDocument($xpsPath, [System.IO.FileAccess]::Read)
353
+ $seq = $xpsDocForPrint.GetFixedDocumentSequence()
354
+
355
+ $xpsWriter = [System.Printing.PrintQueue]::CreateXpsDocumentWriter($queue)
356
+ $xpsWriter.Write($seq, $ticket)
357
+
358
+ $xpsDocForPrint.Close()
359
+ Remove-Item $xpsPath -ErrorAction SilentlyContinue
360
+ `;
361
+ const ps = spawn("powershell", ["-Command", psScript], { stdio: "pipe" });
362
+ let stdout = "";
363
+ let stderr = "";
364
+ ps.stdout.on("data", (data) => { stdout += data.toString(); });
365
+ ps.stderr.on("data", (data) => { stderr += data.toString(); });
366
+ ps.on("close", (code) => {
367
+ if (code === 0) {
368
+ resolve();
369
+ }
370
+ else {
371
+ reject(new Error(`Print failed: ${stderr}`));
372
+ }
373
+ });
374
+ ps.on("error", (err) => {
375
+ reject(new Error(`Failed to print: ${err.message}`));
376
+ });
377
+ });
378
+ }
379
+ finally {
380
+ if (fs.existsSync(tempPath)) {
381
+ fs.unlinkSync(tempPath);
382
+ }
383
+ }
384
+ }
385
+ // Main API functions
386
+ export async function render(options) {
387
+ validateOptions(options);
388
+ const { tape } = resolveSettings(options);
389
+ return renderContent(options, tape);
390
+ }
391
+ export async function print(options) {
392
+ validateOptions(options);
393
+ const { tape, printer } = resolveSettings(options);
394
+ const image = await renderContent(options, tape);
395
+ await printBuffer(image, printer, tape);
396
+ return { image };
397
+ }
398
+ //# sourceMappingURL=api.js.map
package/api.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["api.ts"],"names":[],"mappings":"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"}