@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 +193 -0
- package/api.d.ts +39 -0
- package/api.d.ts.map +1 -0
- package/api.js +398 -0
- package/api.js.map +1 -0
- package/api.ts +488 -0
- package/brother-print.d.ts +3 -0
- package/brother-print.d.ts.map +1 -0
- package/brother-print.js +629 -0
- package/brother-print.js.map +1 -0
- package/brother-print.ts +697 -0
- package/cli.d.ts +7 -0
- package/cli.d.ts.map +1 -0
- package/cli.js +165 -0
- package/cli.js.map +1 -0
- package/cli.ts +180 -0
- package/index.d.ts +6 -0
- package/index.d.ts.map +1 -0
- package/index.js +8 -0
- package/index.js.map +1 -0
- package/index.ts +21 -0
- package/package.json +56 -0
- package/render.d.ts +38 -0
- package/render.d.ts.map +1 -0
- package/render.js +170 -0
- package/render.js.map +1 -0
- package/render.ts +201 -0
- package/tsconfig.json +18 -0
package/brother-print.js
ADDED
|
@@ -0,0 +1,629 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Jimp, loadFont, measureText, measureTextHeight } from "jimp";
|
|
3
|
+
import { program } from "commander";
|
|
4
|
+
import { exec, spawn } from "child_process";
|
|
5
|
+
import * as fs from "fs";
|
|
6
|
+
import * as path from "path";
|
|
7
|
+
import * as os from "os";
|
|
8
|
+
import { renderHtmlFile, closeBrowser } from "./render.js";
|
|
9
|
+
import QRCode from "qrcode";
|
|
10
|
+
const __dirname = import.meta.dirname;
|
|
11
|
+
const CONFIG_PATH = path.join(os.homedir(), ".brother-label.json");
|
|
12
|
+
function loadConfig() {
|
|
13
|
+
try {
|
|
14
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
15
|
+
return JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
// Ignore config errors
|
|
20
|
+
}
|
|
21
|
+
return {};
|
|
22
|
+
}
|
|
23
|
+
function saveConfig(config) {
|
|
24
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
25
|
+
}
|
|
26
|
+
// Available font sizes in jimp
|
|
27
|
+
const FONT_SIZES = [128, 64, 32, 16, 14, 12, 10, 8];
|
|
28
|
+
async function loadFontBySize(size) {
|
|
29
|
+
const fontDir = path.join(__dirname, "node_modules/@jimp/plugin-print/fonts/open-sans");
|
|
30
|
+
const fontFolder = `open-sans-${size}-black`;
|
|
31
|
+
const fontPath = path.join(fontDir, fontFolder, `${fontFolder}.fnt`);
|
|
32
|
+
return loadFont(fontPath);
|
|
33
|
+
}
|
|
34
|
+
async function createLabelImage(text, options) {
|
|
35
|
+
const lines = text.split("\\n").join("\n");
|
|
36
|
+
const targetHeight = options.height;
|
|
37
|
+
// Use largest font for best quality, then scale down
|
|
38
|
+
let font = await loadFontBySize(128);
|
|
39
|
+
// Render text at large size first
|
|
40
|
+
const textWidth = measureText(font, lines);
|
|
41
|
+
const textHeight = measureTextHeight(font, lines, textWidth + 100);
|
|
42
|
+
// Create image for text with small padding
|
|
43
|
+
const padding = 10;
|
|
44
|
+
const imgWidth = textWidth + padding * 2;
|
|
45
|
+
const imgHeight = textHeight + padding * 2;
|
|
46
|
+
const tempImage = new Jimp({ width: imgWidth, height: imgHeight, color: 0xffffffff });
|
|
47
|
+
tempImage.print({
|
|
48
|
+
font: font,
|
|
49
|
+
x: padding,
|
|
50
|
+
y: padding,
|
|
51
|
+
text: lines,
|
|
52
|
+
});
|
|
53
|
+
// Scale to fit tape height (tape sizes already account for printable area)
|
|
54
|
+
const scale = targetHeight / imgHeight;
|
|
55
|
+
const finalWidth = Math.round(imgWidth * scale);
|
|
56
|
+
const finalHeight = Math.round(imgHeight * scale);
|
|
57
|
+
tempImage.resize({ w: finalWidth, h: finalHeight });
|
|
58
|
+
// Create final image sized to content with small horizontal padding
|
|
59
|
+
const hPadding = Math.round(targetHeight * 0.2); // ~20% of height as side margins
|
|
60
|
+
const outputWidth = finalWidth + hPadding * 2;
|
|
61
|
+
const image = new Jimp({ width: outputWidth, height: targetHeight, color: 0xffffffff });
|
|
62
|
+
// Center both horizontally and vertically
|
|
63
|
+
const xOffset = hPadding;
|
|
64
|
+
const yOffset = Math.round((targetHeight - finalHeight) / 2);
|
|
65
|
+
image.composite(tempImage, xOffset, yOffset);
|
|
66
|
+
return image.getBuffer("image/png");
|
|
67
|
+
}
|
|
68
|
+
async function createQrLabelImage(data, options, labelText) {
|
|
69
|
+
const targetHeight = options.height;
|
|
70
|
+
const qrSize = Math.floor(targetHeight * 0.95); // QR code is 95% of tape height
|
|
71
|
+
// Margins in mm converted to pixels at PRINT_DPI
|
|
72
|
+
// Left margin ~2mm, right margin ~4mm to account for printer feed
|
|
73
|
+
const pxPerMm = PRINT_DPI / 25.4;
|
|
74
|
+
const leftMargin = Math.round(2 * pxPerMm);
|
|
75
|
+
const rightMargin = Math.round(4 * pxPerMm);
|
|
76
|
+
// Generate QR code as PNG buffer at high resolution
|
|
77
|
+
const qrBuffer = await QRCode.toBuffer(data, {
|
|
78
|
+
type: "png",
|
|
79
|
+
width: qrSize,
|
|
80
|
+
margin: 0,
|
|
81
|
+
errorCorrectionLevel: "M",
|
|
82
|
+
color: { dark: "#000000", light: "#ffffff" },
|
|
83
|
+
});
|
|
84
|
+
const qrImage = await Jimp.read(qrBuffer);
|
|
85
|
+
if (!labelText) {
|
|
86
|
+
// QR only - create minimal label with margins
|
|
87
|
+
const outputWidth = leftMargin + qrSize + rightMargin;
|
|
88
|
+
const image = new Jimp({ width: outputWidth, height: targetHeight, color: 0xffffffff });
|
|
89
|
+
const yOffset = Math.floor((targetHeight - qrSize) / 2);
|
|
90
|
+
image.composite(qrImage, leftMargin, yOffset);
|
|
91
|
+
return image.getBuffer("image/png");
|
|
92
|
+
}
|
|
93
|
+
// QR + text label
|
|
94
|
+
const font = await loadFontBySize(64);
|
|
95
|
+
const textWidth = measureText(font, labelText);
|
|
96
|
+
const textHeight = measureTextHeight(font, labelText, textWidth + 50);
|
|
97
|
+
// Scale text to fit beside QR
|
|
98
|
+
const maxTextHeight = targetHeight * 0.8;
|
|
99
|
+
const textScale = Math.min(1, maxTextHeight / textHeight);
|
|
100
|
+
const scaledTextWidth = Math.round(textWidth * textScale);
|
|
101
|
+
const scaledTextHeight = Math.round(textHeight * textScale);
|
|
102
|
+
// Create text image
|
|
103
|
+
const textImg = new Jimp({ width: textWidth + 20, height: textHeight + 20, color: 0xffffffff });
|
|
104
|
+
textImg.print({ font, x: 10, y: 10, text: labelText });
|
|
105
|
+
if (textScale < 1) {
|
|
106
|
+
textImg.resize({ w: scaledTextWidth, h: scaledTextHeight });
|
|
107
|
+
}
|
|
108
|
+
// Compose final image: QR on left, text on right
|
|
109
|
+
const gap = Math.floor(targetHeight * 0.15);
|
|
110
|
+
const outputWidth = leftMargin + qrSize + gap + scaledTextWidth + rightMargin;
|
|
111
|
+
const image = new Jimp({ width: outputWidth, height: targetHeight, color: 0xffffffff });
|
|
112
|
+
const qrY = Math.floor((targetHeight - qrSize) / 2);
|
|
113
|
+
image.composite(qrImage, leftMargin, qrY);
|
|
114
|
+
const textY = Math.floor((targetHeight - scaledTextHeight) / 2);
|
|
115
|
+
image.composite(textImg, leftMargin + qrSize + gap, textY);
|
|
116
|
+
return image.getBuffer("image/png");
|
|
117
|
+
}
|
|
118
|
+
async function printImage(imagePath, printerName, tapeMm) {
|
|
119
|
+
// Map tape mm to Brother CustomMediaSize for PrintTicket
|
|
120
|
+
const mediaOptions = {
|
|
121
|
+
6: { name: "CustomMediaSize257", width: 5900 },
|
|
122
|
+
9: { name: "CustomMediaSize258", width: 9000 },
|
|
123
|
+
12: { name: "CustomMediaSize259", width: 11900 },
|
|
124
|
+
18: { name: "CustomMediaSize260", width: 18100 },
|
|
125
|
+
24: { name: "CustomMediaSize261", width: 24000 },
|
|
126
|
+
};
|
|
127
|
+
const media = mediaOptions[tapeMm] || mediaOptions[12];
|
|
128
|
+
return new Promise((resolve, reject) => {
|
|
129
|
+
const psScript = `
|
|
130
|
+
Add-Type -AssemblyName System.Drawing
|
|
131
|
+
Add-Type -AssemblyName System.Printing
|
|
132
|
+
Add-Type -AssemblyName ReachFramework
|
|
133
|
+
Add-Type -AssemblyName PresentationCore
|
|
134
|
+
|
|
135
|
+
$img = [System.Drawing.Image]::FromFile('${imagePath.replace(/\\/g, "\\\\")}')
|
|
136
|
+
|
|
137
|
+
# Calculate label dimensions in microns (using ${PRINT_DPI} DPI source images)
|
|
138
|
+
$labelLengthMicrons = [int]($img.Width / ${PRINT_DPI}.0 * 25400) + 3000
|
|
139
|
+
$tapeWidthMicrons = ${media.width}
|
|
140
|
+
|
|
141
|
+
# Image dimensions in WPF units (1/96 inch) - convert from ${PRINT_DPI} DPI source
|
|
142
|
+
$imgWidthWpf = $img.Width / ${PRINT_DPI}.0 * 96
|
|
143
|
+
$imgHeightWpf = $img.Height / ${PRINT_DPI}.0 * 96
|
|
144
|
+
|
|
145
|
+
Write-Host "Using ${tapeMm}mm tape, label length: $([int]($labelLengthMicrons/1000))mm"
|
|
146
|
+
|
|
147
|
+
# Build PrintTicket XML
|
|
148
|
+
$ticketXml = @"
|
|
149
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
150
|
+
<psf:PrintTicket xmlns:psf="http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework"
|
|
151
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="1"
|
|
152
|
+
xmlns:psk="http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords"
|
|
153
|
+
xmlns:ns0001="http://schemas.brother.info/mfc/printing/2006/11/printschemakeywords">
|
|
154
|
+
<psf:Feature name="psk:PageMediaSize">
|
|
155
|
+
<psf:Option name="ns0001:${media.name}">
|
|
156
|
+
<psf:ScoredProperty name="psk:MediaSizeWidth">
|
|
157
|
+
<psf:Value xsi:type="xsd:integer">${media.width}</psf:Value>
|
|
158
|
+
</psf:ScoredProperty>
|
|
159
|
+
<psf:ScoredProperty name="psk:MediaSizeHeight">
|
|
160
|
+
<psf:ParameterRef name="psk:PageMediaSizeMediaSizeHeight" />
|
|
161
|
+
</psf:ScoredProperty>
|
|
162
|
+
</psf:Option>
|
|
163
|
+
</psf:Feature>
|
|
164
|
+
<psf:ParameterInit name="psk:PageMediaSizeMediaSizeHeight">
|
|
165
|
+
<psf:Value xsi:type="xsd:integer">$labelLengthMicrons</psf:Value>
|
|
166
|
+
</psf:ParameterInit>
|
|
167
|
+
<psf:Feature name="psk:PageOrientation">
|
|
168
|
+
<psf:Option name="psk:Landscape" />
|
|
169
|
+
</psf:Feature>
|
|
170
|
+
<psf:Feature name="ns0001:PageRollFeedToEndOfSheet">
|
|
171
|
+
<psf:Option name="ns0001:FeedToImageEdge" />
|
|
172
|
+
</psf:Feature>
|
|
173
|
+
<psf:Feature name="psk:PageMediaType">
|
|
174
|
+
<psf:Option name="psk:Label" />
|
|
175
|
+
</psf:Feature>
|
|
176
|
+
<psf:Feature name="ns0001:JobRollCutSheet">
|
|
177
|
+
<psf:Option name="ns0001:CutSheet" />
|
|
178
|
+
</psf:Feature>
|
|
179
|
+
</psf:PrintTicket>
|
|
180
|
+
"@
|
|
181
|
+
|
|
182
|
+
$xmlBytes = [System.Text.Encoding]::UTF8.GetBytes($ticketXml)
|
|
183
|
+
$memStream = New-Object System.IO.MemoryStream(,$xmlBytes)
|
|
184
|
+
$ticket = New-Object System.Printing.PrintTicket($memStream)
|
|
185
|
+
|
|
186
|
+
# Get print queue and create XPS document writer with our ticket
|
|
187
|
+
$server = New-Object System.Printing.LocalPrintServer
|
|
188
|
+
$queue = $server.GetPrintQueue('${printerName}')
|
|
189
|
+
|
|
190
|
+
# Create temp XPS file
|
|
191
|
+
$xpsPath = [System.IO.Path]::GetTempFileName() + ".xps"
|
|
192
|
+
|
|
193
|
+
# Page size in WPF units (96 dpi) - convert from microns
|
|
194
|
+
$pageWidth = $labelLengthMicrons / 25400.0 * 96 # length is horizontal
|
|
195
|
+
$pageHeight = $tapeWidthMicrons / 25400.0 * 96 # tape width is vertical
|
|
196
|
+
|
|
197
|
+
# Create XPS document
|
|
198
|
+
$package = [System.IO.Packaging.Package]::Open($xpsPath, [System.IO.FileMode]::Create)
|
|
199
|
+
$xpsDoc = New-Object System.Windows.Xps.Packaging.XpsDocument($package)
|
|
200
|
+
$writer = [System.Windows.Xps.Packaging.XpsDocument]::CreateXpsDocumentWriter($xpsDoc)
|
|
201
|
+
|
|
202
|
+
# Create visual with image
|
|
203
|
+
$visual = New-Object System.Windows.Media.DrawingVisual
|
|
204
|
+
$dc = $visual.RenderOpen()
|
|
205
|
+
|
|
206
|
+
# Load image as WPF bitmap
|
|
207
|
+
$bitmapImg = New-Object System.Windows.Media.Imaging.BitmapImage
|
|
208
|
+
$bitmapImg.BeginInit()
|
|
209
|
+
$bitmapImg.UriSource = New-Object System.Uri('${imagePath.replace(/\\/g, "\\\\")}')
|
|
210
|
+
$bitmapImg.EndInit()
|
|
211
|
+
|
|
212
|
+
# Draw image centered vertically on page
|
|
213
|
+
$yOffset = ($pageHeight - $imgHeightWpf) / 2
|
|
214
|
+
$rect = New-Object System.Windows.Rect(0, $yOffset, $imgWidthWpf, $imgHeightWpf)
|
|
215
|
+
$dc.DrawImage($bitmapImg, $rect)
|
|
216
|
+
$dc.Close()
|
|
217
|
+
|
|
218
|
+
# Write to XPS with page size
|
|
219
|
+
$pageSize = New-Object System.Printing.PageMediaSize($pageWidth, $pageHeight)
|
|
220
|
+
$writer.Write($visual, $ticket)
|
|
221
|
+
|
|
222
|
+
$xpsDoc.Close()
|
|
223
|
+
$package.Close()
|
|
224
|
+
$img.Dispose()
|
|
225
|
+
|
|
226
|
+
# Print the XPS file with our ticket
|
|
227
|
+
$xpsDocForPrint = New-Object System.Windows.Xps.Packaging.XpsDocument($xpsPath, [System.IO.FileAccess]::Read)
|
|
228
|
+
$seq = $xpsDocForPrint.GetFixedDocumentSequence()
|
|
229
|
+
|
|
230
|
+
$xpsWriter = [System.Printing.PrintQueue]::CreateXpsDocumentWriter($queue)
|
|
231
|
+
$xpsWriter.Write($seq, $ticket)
|
|
232
|
+
|
|
233
|
+
$xpsDocForPrint.Close()
|
|
234
|
+
Remove-Item $xpsPath -ErrorAction SilentlyContinue
|
|
235
|
+
|
|
236
|
+
Write-Host "Print complete"
|
|
237
|
+
`;
|
|
238
|
+
const ps = spawn("powershell", ["-Command", psScript], { stdio: "pipe" });
|
|
239
|
+
let stdout = "";
|
|
240
|
+
let stderr = "";
|
|
241
|
+
ps.stdout.on("data", (data) => {
|
|
242
|
+
stdout += data.toString();
|
|
243
|
+
});
|
|
244
|
+
ps.stderr.on("data", (data) => {
|
|
245
|
+
stderr += data.toString();
|
|
246
|
+
});
|
|
247
|
+
ps.on("close", (code) => {
|
|
248
|
+
if (stdout)
|
|
249
|
+
console.log(stdout.trim());
|
|
250
|
+
if (code === 0) {
|
|
251
|
+
resolve();
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
reject(new Error(`Print failed: ${stderr}`));
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
ps.on("error", (err) => {
|
|
258
|
+
reject(new Error(`Failed to print: ${err.message}`));
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
async function printLabel(text, options) {
|
|
263
|
+
// Create temp file for the image
|
|
264
|
+
const tempDir = os.tmpdir();
|
|
265
|
+
const tempFile = path.join(tempDir, `label-${Date.now()}.png`);
|
|
266
|
+
try {
|
|
267
|
+
const imageBuffer = await createLabelImage(text, options);
|
|
268
|
+
fs.writeFileSync(tempFile, imageBuffer);
|
|
269
|
+
await printImage(tempFile, options.printer, options.tapeMm);
|
|
270
|
+
}
|
|
271
|
+
finally {
|
|
272
|
+
// Clean up temp file
|
|
273
|
+
if (fs.existsSync(tempFile)) {
|
|
274
|
+
fs.unlinkSync(tempFile);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
async function printHtmlLabel(htmlPath, options) {
|
|
279
|
+
const tempDir = os.tmpdir();
|
|
280
|
+
const tempFile = path.join(tempDir, `label-html-${Date.now()}.png`);
|
|
281
|
+
try {
|
|
282
|
+
// CSS mm units use 96 DPI. Convert tape mm to CSS pixels, then scale up.
|
|
283
|
+
// For 12mm tape: 12mm * 3.78 px/mm = ~45px CSS height
|
|
284
|
+
// deviceScaleFactor of 300/96 ≈ 3.125 gives us 300 DPI output
|
|
285
|
+
const cssPixelsPerMm = 96 / 25.4; // ~3.78
|
|
286
|
+
const viewportHeight = Math.round(options.tapeMm * cssPixelsPerMm);
|
|
287
|
+
const viewportWidth = Math.round(viewportHeight * 5); // ~5:1 aspect for labels
|
|
288
|
+
const scaleFactor = PRINT_DPI / 96; // Scale CSS pixels to print DPI
|
|
289
|
+
const renderedBuffer = await renderHtmlFile(htmlPath, {
|
|
290
|
+
width: viewportWidth,
|
|
291
|
+
height: viewportHeight,
|
|
292
|
+
deviceScaleFactor: scaleFactor,
|
|
293
|
+
keepScale: true, // Keep full resolution for printing
|
|
294
|
+
});
|
|
295
|
+
// Add margins for printer feed (3mm left, 4mm right)
|
|
296
|
+
const pxPerMm = PRINT_DPI / 25.4;
|
|
297
|
+
const leftMargin = Math.round(3 * pxPerMm);
|
|
298
|
+
const rightMargin = Math.round(4 * pxPerMm);
|
|
299
|
+
const rendered = await Jimp.read(renderedBuffer);
|
|
300
|
+
const paddedWidth = rendered.width + leftMargin + rightMargin;
|
|
301
|
+
const padded = new Jimp({ width: paddedWidth, height: rendered.height, color: 0xffffffff });
|
|
302
|
+
padded.composite(rendered, leftMargin, 0);
|
|
303
|
+
const imageBuffer = await padded.getBuffer("image/png");
|
|
304
|
+
fs.writeFileSync(tempFile, imageBuffer);
|
|
305
|
+
await printImage(tempFile, options.printer, options.tapeMm);
|
|
306
|
+
}
|
|
307
|
+
finally {
|
|
308
|
+
if (fs.existsSync(tempFile)) {
|
|
309
|
+
fs.unlinkSync(tempFile);
|
|
310
|
+
}
|
|
311
|
+
await closeBrowser();
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
async function listPrinters() {
|
|
315
|
+
return new Promise((resolve, reject) => {
|
|
316
|
+
exec('powershell -Command "Get-Printer | Where-Object { $_.Name -like \'*Brother*\' -or $_.Name -like \'*PT*\' } | Select-Object -ExpandProperty Name"', (error, stdout, stderr) => {
|
|
317
|
+
if (error) {
|
|
318
|
+
reject(new Error(`Failed to list printers: ${stderr}`));
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
const printers = stdout.trim().split("\n").filter(p => p.trim());
|
|
322
|
+
if (printers.length === 0) {
|
|
323
|
+
console.log("No Brother printers found");
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
console.log("Brother printers:");
|
|
327
|
+
printers.forEach(p => console.log(` ${p.trim()}`));
|
|
328
|
+
}
|
|
329
|
+
resolve();
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
async function detectTapeSize(printerName) {
|
|
334
|
+
// First check config file for user-specified tape size
|
|
335
|
+
const config = loadConfig();
|
|
336
|
+
if (config.defaultTape) {
|
|
337
|
+
const mm = parseInt(config.defaultTape.replace("mm", ""), 10);
|
|
338
|
+
if (!isNaN(mm) && TAPE_SIZES[`${mm}mm`]) {
|
|
339
|
+
return mm;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
// Fall back to WMI query (may be stale after tape change)
|
|
343
|
+
return new Promise((resolve) => {
|
|
344
|
+
exec(`powershell -Command "(Get-WmiObject Win32_PrinterConfiguration -Filter \\"Name='${printerName}'\\").PaperWidth"`, (error, stdout) => {
|
|
345
|
+
if (error || !stdout.trim()) {
|
|
346
|
+
resolve(null);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
// PaperWidth is in tenths of mm
|
|
350
|
+
const tenthsMm = parseInt(stdout.trim(), 10);
|
|
351
|
+
if (isNaN(tenthsMm)) {
|
|
352
|
+
resolve(null);
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
const mm = Math.round(tenthsMm / 10);
|
|
356
|
+
resolve(mm);
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
// Default printer name
|
|
361
|
+
const DEFAULT_PRINTER = "Brother PT-P710BT";
|
|
362
|
+
// Label sizes for P-touch tapes at 300 DPI (high quality)
|
|
363
|
+
// PT-P710BT has 180 DPI print head; 300 DPI source ensures max quality
|
|
364
|
+
// Printable area from printer: 0.71" height for 24mm tape, proportional for others
|
|
365
|
+
const PRINT_DPI = 300;
|
|
366
|
+
const TAPE_SIZES = {
|
|
367
|
+
"6mm": { width: 1137, height: 56, mm: 6 }, // 3.79" x 0.19" @ 300 DPI
|
|
368
|
+
"9mm": { width: 1137, height: 84, mm: 9 }, // 3.79" x 0.28" @ 300 DPI
|
|
369
|
+
"12mm": { width: 1137, height: 113, mm: 12 }, // 3.79" x 0.38" @ 300 DPI
|
|
370
|
+
"18mm": { width: 1137, height: 169, mm: 18 }, // 3.79" x 0.56" @ 300 DPI
|
|
371
|
+
"24mm": { width: 1137, height: 213, mm: 24 }, // 3.79" x 0.71" @ 300 DPI
|
|
372
|
+
};
|
|
373
|
+
program
|
|
374
|
+
.name("brother-print")
|
|
375
|
+
.description("Print labels to Brother P-touch and QL label printers")
|
|
376
|
+
.version("1.0.0");
|
|
377
|
+
program
|
|
378
|
+
.command("print <text>")
|
|
379
|
+
.description("Print a text label (use \\\\n for newlines)")
|
|
380
|
+
.option("-p, --printer <name>", "Printer name", DEFAULT_PRINTER)
|
|
381
|
+
.option("-t, --tape <size>", "Tape size: 6mm, 9mm, 12mm, 18mm, 24mm, or 'auto'", "auto")
|
|
382
|
+
.option("-w, --width <px>", "Custom width in pixels")
|
|
383
|
+
.option("-H, --img-height <px>", "Custom height in pixels")
|
|
384
|
+
.action(async (text, opts) => {
|
|
385
|
+
try {
|
|
386
|
+
let tapeMm;
|
|
387
|
+
let tapeSize;
|
|
388
|
+
if (opts.tape === "auto") {
|
|
389
|
+
const detected = await detectTapeSize(opts.printer);
|
|
390
|
+
if (detected) {
|
|
391
|
+
tapeMm = detected;
|
|
392
|
+
tapeSize = TAPE_SIZES[`${detected}mm`] || TAPE_SIZES["24mm"];
|
|
393
|
+
console.log(`Detected ${detected}mm tape`);
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
console.log("Could not detect tape, using 24mm");
|
|
397
|
+
tapeMm = 24;
|
|
398
|
+
tapeSize = TAPE_SIZES["24mm"];
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
tapeSize = TAPE_SIZES[opts.tape] || TAPE_SIZES["24mm"];
|
|
403
|
+
tapeMm = tapeSize.mm;
|
|
404
|
+
}
|
|
405
|
+
const options = {
|
|
406
|
+
printer: opts.printer,
|
|
407
|
+
fontSize: 32,
|
|
408
|
+
width: opts.width ? parseInt(opts.width, 10) : tapeSize.width, // label length
|
|
409
|
+
height: opts.imgHeight ? parseInt(opts.imgHeight, 10) : tapeSize.height, // tape height (printable)
|
|
410
|
+
tapeMm: tapeMm,
|
|
411
|
+
};
|
|
412
|
+
await printLabel(text, options);
|
|
413
|
+
console.log("Label printed successfully");
|
|
414
|
+
}
|
|
415
|
+
catch (err) {
|
|
416
|
+
console.error(`Error: ${err.message}`);
|
|
417
|
+
process.exit(1);
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
program
|
|
421
|
+
.command("list")
|
|
422
|
+
.description("List connected Brother printers")
|
|
423
|
+
.action(async () => {
|
|
424
|
+
try {
|
|
425
|
+
await listPrinters();
|
|
426
|
+
}
|
|
427
|
+
catch (err) {
|
|
428
|
+
console.error(`Error: ${err.message}`);
|
|
429
|
+
process.exit(1);
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
program
|
|
433
|
+
.command("image <file>")
|
|
434
|
+
.description("Print an image file (PNG, JPG, BMP)")
|
|
435
|
+
.option("-p, --printer <name>", "Printer name", DEFAULT_PRINTER)
|
|
436
|
+
.option("-t, --tape <size>", "Tape size: 6mm, 9mm, 12mm, 18mm, 24mm, or 'auto'", "auto")
|
|
437
|
+
.action(async (file, opts) => {
|
|
438
|
+
try {
|
|
439
|
+
let tapeMm;
|
|
440
|
+
let tapeSize;
|
|
441
|
+
if (opts.tape === "auto") {
|
|
442
|
+
const detected = await detectTapeSize(opts.printer);
|
|
443
|
+
if (detected) {
|
|
444
|
+
tapeMm = detected;
|
|
445
|
+
tapeSize = TAPE_SIZES[`${detected}mm`] || TAPE_SIZES["24mm"];
|
|
446
|
+
console.log(`Detected ${detected}mm tape`);
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
console.log("Could not detect tape, using 24mm");
|
|
450
|
+
tapeMm = 24;
|
|
451
|
+
tapeSize = TAPE_SIZES["24mm"];
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
455
|
+
tapeSize = TAPE_SIZES[opts.tape] || TAPE_SIZES["24mm"];
|
|
456
|
+
tapeMm = tapeSize.mm;
|
|
457
|
+
}
|
|
458
|
+
const absolutePath = path.resolve(file);
|
|
459
|
+
await printImage(absolutePath, opts.printer, tapeMm);
|
|
460
|
+
console.log("Image printed successfully");
|
|
461
|
+
}
|
|
462
|
+
catch (err) {
|
|
463
|
+
console.error(`Error: ${err.message}`);
|
|
464
|
+
process.exit(1);
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
program
|
|
468
|
+
.command("html <file>")
|
|
469
|
+
.description("Print an HTML file as a label")
|
|
470
|
+
.option("-p, --printer <name>", "Printer name", DEFAULT_PRINTER)
|
|
471
|
+
.option("-t, --tape <size>", "Tape size: 6mm, 9mm, 12mm, 18mm, 24mm, or 'auto'", "auto")
|
|
472
|
+
.action(async (file, opts) => {
|
|
473
|
+
try {
|
|
474
|
+
let tapeMm;
|
|
475
|
+
let tapeSize;
|
|
476
|
+
if (opts.tape === "auto") {
|
|
477
|
+
const detected = await detectTapeSize(opts.printer);
|
|
478
|
+
if (detected) {
|
|
479
|
+
tapeMm = detected;
|
|
480
|
+
tapeSize = TAPE_SIZES[`${detected}mm`] || TAPE_SIZES["24mm"];
|
|
481
|
+
console.log(`Detected ${detected}mm tape`);
|
|
482
|
+
}
|
|
483
|
+
else {
|
|
484
|
+
console.log("Could not detect tape, using 24mm");
|
|
485
|
+
tapeMm = 24;
|
|
486
|
+
tapeSize = TAPE_SIZES["24mm"];
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
tapeSize = TAPE_SIZES[opts.tape] || TAPE_SIZES["24mm"];
|
|
491
|
+
tapeMm = tapeSize.mm;
|
|
492
|
+
}
|
|
493
|
+
const options = {
|
|
494
|
+
printer: opts.printer,
|
|
495
|
+
fontSize: 32,
|
|
496
|
+
width: tapeSize.width, // label length
|
|
497
|
+
height: tapeSize.height, // tape height (printable)
|
|
498
|
+
tapeMm: tapeMm,
|
|
499
|
+
};
|
|
500
|
+
await printHtmlLabel(file, options);
|
|
501
|
+
console.log("HTML label printed successfully");
|
|
502
|
+
}
|
|
503
|
+
catch (err) {
|
|
504
|
+
console.error(`Error: ${err.message}`);
|
|
505
|
+
process.exit(1);
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
program
|
|
509
|
+
.command("preview <text>")
|
|
510
|
+
.description("Save label as PNG without printing")
|
|
511
|
+
.option("-f, --font-size <size>", "Font size (16 or 32)", "32")
|
|
512
|
+
.option("-t, --tape <size>", "Tape size: 6mm, 9mm, 12mm, 18mm, 24mm", "12mm")
|
|
513
|
+
.option("-w, --width <px>", "Custom width in pixels")
|
|
514
|
+
.option("-H, --img-height <px>", "Custom height in pixels")
|
|
515
|
+
.option("-o, --output <file>", "Output file path", "label-preview.png")
|
|
516
|
+
.action(async (text, opts) => {
|
|
517
|
+
try {
|
|
518
|
+
const tapeSize = TAPE_SIZES[opts.tape] || TAPE_SIZES["12mm"];
|
|
519
|
+
const options = {
|
|
520
|
+
printer: "",
|
|
521
|
+
fontSize: parseInt(opts.fontSize, 10),
|
|
522
|
+
width: opts.width ? parseInt(opts.width, 10) : tapeSize.width, // label length
|
|
523
|
+
height: opts.imgHeight ? parseInt(opts.imgHeight, 10) : tapeSize.height, // tape height
|
|
524
|
+
tapeMm: tapeSize.mm,
|
|
525
|
+
};
|
|
526
|
+
const imageBuffer = await createLabelImage(text, options);
|
|
527
|
+
fs.writeFileSync(opts.output, imageBuffer);
|
|
528
|
+
console.log(`Preview saved to ${opts.output}`);
|
|
529
|
+
}
|
|
530
|
+
catch (err) {
|
|
531
|
+
console.error(`Error: ${err.message}`);
|
|
532
|
+
process.exit(1);
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
program
|
|
536
|
+
.command("qr <data>")
|
|
537
|
+
.description("Print a QR code label")
|
|
538
|
+
.option("-p, --printer <name>", "Printer name", DEFAULT_PRINTER)
|
|
539
|
+
.option("-t, --tape <size>", "Tape size: 6mm, 9mm, 12mm, 18mm, 24mm, or 'auto'", "auto")
|
|
540
|
+
.option("-l, --label <text>", "Optional text label beside QR code")
|
|
541
|
+
.option("-o, --output <file>", "Save to file instead of printing")
|
|
542
|
+
.action(async (data, opts) => {
|
|
543
|
+
try {
|
|
544
|
+
let tapeMm;
|
|
545
|
+
let tapeSize;
|
|
546
|
+
if (opts.tape === "auto") {
|
|
547
|
+
const detected = await detectTapeSize(opts.printer);
|
|
548
|
+
if (detected) {
|
|
549
|
+
tapeMm = detected;
|
|
550
|
+
tapeSize = TAPE_SIZES[`${detected}mm`] || TAPE_SIZES["24mm"];
|
|
551
|
+
console.log(`Detected ${detected}mm tape`);
|
|
552
|
+
}
|
|
553
|
+
else {
|
|
554
|
+
console.log("Could not detect tape, using 24mm");
|
|
555
|
+
tapeMm = 24;
|
|
556
|
+
tapeSize = TAPE_SIZES["24mm"];
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
else {
|
|
560
|
+
tapeSize = TAPE_SIZES[opts.tape] || TAPE_SIZES["24mm"];
|
|
561
|
+
tapeMm = tapeSize.mm;
|
|
562
|
+
}
|
|
563
|
+
const options = {
|
|
564
|
+
printer: opts.printer,
|
|
565
|
+
fontSize: 32,
|
|
566
|
+
width: tapeSize.width,
|
|
567
|
+
height: tapeSize.height,
|
|
568
|
+
tapeMm: tapeMm,
|
|
569
|
+
};
|
|
570
|
+
const imageBuffer = await createQrLabelImage(data, options, opts.label);
|
|
571
|
+
if (opts.output) {
|
|
572
|
+
fs.writeFileSync(opts.output, imageBuffer);
|
|
573
|
+
console.log(`QR label saved to ${opts.output}`);
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
const tempDir = os.tmpdir();
|
|
577
|
+
const tempFile = path.join(tempDir, `qr-label-${Date.now()}.png`);
|
|
578
|
+
try {
|
|
579
|
+
fs.writeFileSync(tempFile, imageBuffer);
|
|
580
|
+
await printImage(tempFile, options.printer, options.tapeMm);
|
|
581
|
+
console.log("QR label printed successfully");
|
|
582
|
+
}
|
|
583
|
+
finally {
|
|
584
|
+
if (fs.existsSync(tempFile)) {
|
|
585
|
+
fs.unlinkSync(tempFile);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
catch (err) {
|
|
591
|
+
console.error(`Error: ${err.message}`);
|
|
592
|
+
process.exit(1);
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
program
|
|
596
|
+
.command("config")
|
|
597
|
+
.description("Set default tape size and printer (stored in ~/.brother-label.json)")
|
|
598
|
+
.option("-t, --tape <size>", "Set default tape size: 6mm, 9mm, 12mm, 18mm, 24mm")
|
|
599
|
+
.option("-p, --printer <name>", "Set default printer name")
|
|
600
|
+
.option("-s, --show", "Show current configuration")
|
|
601
|
+
.action((opts) => {
|
|
602
|
+
const config = loadConfig();
|
|
603
|
+
if (opts.show || (!opts.tape && !opts.printer)) {
|
|
604
|
+
console.log("Current configuration:");
|
|
605
|
+
console.log(` Config file: ${CONFIG_PATH}`);
|
|
606
|
+
console.log(` Default tape: ${config.defaultTape || "(not set - will use WMI detection)"}`);
|
|
607
|
+
console.log(` Default printer: ${config.defaultPrinter || DEFAULT_PRINTER}`);
|
|
608
|
+
console.log("\nAvailable tape sizes: 6mm, 9mm, 12mm, 18mm, 24mm");
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
if (opts.tape) {
|
|
612
|
+
const tape = opts.tape.endsWith("mm") ? opts.tape : `${opts.tape}mm`;
|
|
613
|
+
if (!TAPE_SIZES[tape]) {
|
|
614
|
+
console.error(`Invalid tape size: ${opts.tape}`);
|
|
615
|
+
console.error("Valid sizes: 6mm, 9mm, 12mm, 18mm, 24mm");
|
|
616
|
+
process.exit(1);
|
|
617
|
+
}
|
|
618
|
+
config.defaultTape = tape;
|
|
619
|
+
console.log(`Default tape set to: ${tape}`);
|
|
620
|
+
}
|
|
621
|
+
if (opts.printer) {
|
|
622
|
+
config.defaultPrinter = opts.printer;
|
|
623
|
+
console.log(`Default printer set to: ${opts.printer}`);
|
|
624
|
+
}
|
|
625
|
+
saveConfig(config);
|
|
626
|
+
console.log(`Configuration saved to ${CONFIG_PATH}`);
|
|
627
|
+
});
|
|
628
|
+
program.parse();
|
|
629
|
+
//# sourceMappingURL=brother-print.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brother-print.js","sourceRoot":"","sources":["brother-print.ts"],"names":[],"mappings":"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"}
|