libniimai 0.5.0 → 0.6.0
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 +9 -8
- package/dist/bluetooth.d.ts +2 -43
- package/dist/catalog.d.ts +21 -1
- package/dist/client.d.ts +9 -6
- package/dist/index.d.ts +7 -4
- package/dist/libniimai.js +246 -77
- package/dist/libniimai.js.map +1 -1
- package/dist/routed.d.ts +52 -0
- package/dist/thermal.d.ts +5 -1
- package/dist/usb.d.ts +39 -0
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# libniimai
|
|
2
2
|
|
|
3
|
-
Print from the browser on four families of thermal printers: **NIIMBOT**, **TSPL label printers**, **ESC/POS receipt printers** and **cat printers**. One API connects, detects the printer and prints any canvas, over Web Bluetooth
|
|
3
|
+
Print from the browser on four families of thermal printers: **NIIMBOT**, **TSPL label printers**, **ESC/POS receipt printers** and **cat printers**. One API connects, detects the printer and prints any canvas, over Web Bluetooth, Web Serial or WebUSB. No server, no drivers, no app.
|
|
4
4
|
|
|
5
5
|
libniimai powers [niimai](https://niimai.app), the label designer.
|
|
6
6
|
|
|
@@ -9,8 +9,8 @@ libniimai powers [niimai](https://niimai.app), the label designer.
|
|
|
9
9
|
| Family | Paper | Print width | Connection | Models |
|
|
10
10
|
|---|---|---|---|---|
|
|
11
11
|
| **NIIMBOT** | Labels with gaps, black mark, continuous, transparent | 12 mm and up, by model | Bluetooth, USB | D11, D110, D101, B1, B18, B21, B3S and more |
|
|
12
|
-
| **TSPL label printers** | Labels with gaps, black mark, continuous | Up to 80 mm | Bluetooth | QR380A (sold as CC390), Gprinter GP-M322 |
|
|
13
|
-
| **ESC/POS receipt printers** | 58 or 80 mm, continuous or stickers with gaps | 48 or 72 mm | Bluetooth | MP583, MPT-II, Xprinter XP-58IIL, PT-210, RPP02, MPT-3, RPP300 and more |
|
|
12
|
+
| **TSPL label printers** | Labels with gaps, black mark, continuous | Up to 80 mm | Bluetooth, USB | QR380A (sold as CC390), Gprinter GP-M322 |
|
|
13
|
+
| **ESC/POS receipt printers** | 58 or 80 mm, continuous or stickers with gaps | 48 or 72 mm | Bluetooth, USB | MP583, MPT-II, Xprinter XP-58IIL, PT-210, RPP02, MPT-3, RPP300 and more |
|
|
14
14
|
| **Cat printers** | 58 mm continuous, stickers with gaps | 48 mm | Bluetooth | GB01, GB02, GB03, MX05, MX06, MX10 and more |
|
|
15
15
|
|
|
16
16
|
The family is found from the device the user picks: by its Bluetooth name in `PRINTER_CATALOG`, then checked against the services it offers. A name that matches no family is treated as a NIIMBOT, unless a type from `PRINTER_TYPES` is set for unrecognised printers. Every family gets the same treatment:
|
|
@@ -90,7 +90,7 @@ Returns a `PrinterService`, which owns one printer connection.
|
|
|
90
90
|
|
|
91
91
|
| Member | What it does |
|
|
92
92
|
| --- | --- |
|
|
93
|
-
| `connect(kind)` | Opens the browser's device picker and connects. `kind` is `'bluetooth'` (every family), `'serial'` (NIIMBOT over USB) or `'demo'` (a printer in memory, for trying things out). |
|
|
93
|
+
| `connect(kind)` | Opens the browser's device picker and connects. `kind` is `'bluetooth'` (every family), `'serial'` (NIIMBOT over USB, as a serial port), `'usb'` (label and receipt printers that show up as standard USB printers) or `'demo'` (a printer in memory, for trying things out). |
|
|
94
94
|
| `disconnect()` | Closes the connection. |
|
|
95
95
|
| `print(source, options)` | Prints a canvas, or a `{ count, page(i) }` source for a batch of different labels. |
|
|
96
96
|
| `getStatus()` | The current `PrinterStatus`. |
|
|
@@ -159,14 +159,15 @@ Every piece is exported, for building your own flow:
|
|
|
159
159
|
- `createClient(kind)` returns a raw client for one connection.
|
|
160
160
|
- `TsplPrinterClient`, `EscPosPrinterClient` and `CatPrinterClient` take any `ThermalTransport`, so they also work over other links.
|
|
161
161
|
- `tsplJob`, `escposJob` and `catJob` build the bytes for one page; `escposFeed` and `catFeed` the bytes that move the paper.
|
|
162
|
-
- `identifyPrinter(name)` matches a Bluetooth name to a known model across every family, from `PRINTER_CATALOG`; `tsplModelFor`, `escposModelFor` and `catModelFor` look in one family.
|
|
163
|
-
- `
|
|
162
|
+
- `identifyPrinter(name)` matches a Bluetooth name to a known model across every family, from `PRINTER_CATALOG`; `tsplModelFor`, `escposModelFor` and `catModelFor` look in one family. `identifyUsbPrinter(device)` does the same for a USB device, by vendor and product ID, then product name.
|
|
163
|
+
- `UsbPrinter` connects over WebUSB to a printer-class device (`USB_PRINTER_CLASS`, 7). The family comes from the catalog, then from a type set with `unrecognisedAs` when the printer speaks it, then from the printer's IEEE 1284 device ID (`familiesFromDeviceId`). A printer the site already uses connects without the chooser when it is the only one plugged in; `rememberedUsbPrinters()` lists them. `usbTransport(device)` gives the raw `ThermalTransport`.
|
|
164
|
+
- `supportIssue(kind)` says why a connection type cannot be used in the current browser, as `{ reason, topic }`, or null when it can. `topic` names what fixes it: `linux` (a Chrome flag), `brave` (Brave flags), `ios`, `https`, `usb` (Windows and Linux drivers holding a USB printer) or `browsers`. `unsupportedReason(kind)` returns the reason alone.
|
|
164
165
|
- `detectBrowser()` returns the system, the browser and whether it is built on Chromium.
|
|
165
|
-
- `connectErrorTopic(err)` maps a connect error from a browser that has Bluetooth but cannot use it (adapter off, API turned off) to the same topics.
|
|
166
|
+
- `connectErrorTopic(err)` maps a connect error from a browser that has Bluetooth or USB but cannot use it (adapter off, API turned off, a system driver holding the printer) to the same topics.
|
|
166
167
|
|
|
167
168
|
## Browsers
|
|
168
169
|
|
|
169
|
-
Needs Web Bluetooth
|
|
170
|
+
Needs Web Bluetooth, Web Serial or WebUSB: Chrome or Edge on desktop, or Chrome on Android. On iPhone and iPad, the Bluefy browser adds Web Bluetooth. On Linux, Chrome needs `chrome://flags/#enable-web-bluetooth` turned on; Brave keeps Bluetooth and serial behind `brave://flags`. For USB printers, Windows needs the WinUSB driver (Zadig installs it), and Linux needs the `usblp` module unloaded and a udev rule granting access.
|
|
170
171
|
|
|
171
172
|
## Feedback
|
|
172
173
|
|
package/dist/bluetooth.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { RoutedClient } from './routed.js';
|
|
2
2
|
type Lib = typeof import('@mmote/niimbluelib');
|
|
3
3
|
/**
|
|
4
4
|
* The Bluetooth printer behind the Connect button. One chooser lists NIIMBOT
|
|
@@ -9,55 +9,14 @@ type Lib = typeof import('@mmote/niimbluelib');
|
|
|
9
9
|
* the TSPL client; and everything else the NIIMBOT client exactly as before.
|
|
10
10
|
* Known names never overlap, so each printer matches one client at most.
|
|
11
11
|
*/
|
|
12
|
-
export declare class BluetoothPrinter
|
|
12
|
+
export declare class BluetoothPrinter extends RoutedClient {
|
|
13
13
|
private lib;
|
|
14
|
-
private inner;
|
|
15
14
|
constructor(lib: () => Promise<Lib>);
|
|
16
|
-
private get client();
|
|
17
15
|
/** The kind of printer to treat an unrecognised one as; null leaves it to NIIMBOT. */
|
|
18
16
|
private fallback;
|
|
19
17
|
unrecognisedAs(typeId: string | null): void;
|
|
20
18
|
connect(): Promise<{
|
|
21
19
|
deviceName?: string;
|
|
22
20
|
}>;
|
|
23
|
-
disconnect(): Promise<void>;
|
|
24
|
-
isConnected(): boolean;
|
|
25
|
-
on(event: string, fn: (e: any) => void): unknown;
|
|
26
|
-
off(event: string, fn: (e: any) => void): unknown;
|
|
27
|
-
getPrinterInfo(): {
|
|
28
|
-
batteryPercents?: number;
|
|
29
|
-
modelId?: number;
|
|
30
|
-
printheadWidth?: number;
|
|
31
|
-
protocolVersion?: number;
|
|
32
|
-
};
|
|
33
|
-
getModelMetadata(): import("@mmote/niimbluelib").PrinterModelMeta | undefined;
|
|
34
|
-
getPrintTaskType(): "B1" | "B21_L2B" | "B21_V1" | "D110" | "D110M_V4" | "D11_V1" | "H1S" | undefined;
|
|
35
|
-
getRfidInfo(): {
|
|
36
|
-
labelRfidInfo?: {
|
|
37
|
-
tagPresent?: boolean;
|
|
38
|
-
barCode?: string;
|
|
39
|
-
allPaper?: number;
|
|
40
|
-
usedPaper?: number;
|
|
41
|
-
consumablesType?: number;
|
|
42
|
-
};
|
|
43
|
-
paperInfo?: {
|
|
44
|
-
valid?: boolean;
|
|
45
|
-
paperWidth?: number;
|
|
46
|
-
paperHeight?: number;
|
|
47
|
-
paperType?: number;
|
|
48
|
-
};
|
|
49
|
-
};
|
|
50
|
-
fetchRfidInfo(): Promise<unknown>;
|
|
51
|
-
startHeartbeat(): void;
|
|
52
|
-
stopHeartbeat(): void;
|
|
53
|
-
isHeartbeatStarted(): boolean;
|
|
54
|
-
get protocol(): {
|
|
55
|
-
newPrintTask(name: import("@mmote/niimbluelib").PrintTaskName, options: Record<string, unknown>): import("./client.js").PrintTaskLike;
|
|
56
|
-
printEnd(): Promise<boolean>;
|
|
57
|
-
};
|
|
58
|
-
get encodePage(): ((canvas: HTMLCanvasElement) => unknown) | undefined;
|
|
59
|
-
get rollKey(): (() => string) | undefined;
|
|
60
|
-
get feedPaper(): ((dots: number) => Promise<void>) | undefined;
|
|
61
|
-
get feedsBack(): boolean | undefined;
|
|
62
21
|
}
|
|
63
22
|
export {};
|
package/dist/catalog.d.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Every printer outside NIIMBOT that libniimai knows, by Bluetooth name, in
|
|
3
|
+
* one lookup across families. A name matches one family at most, and a name
|
|
4
|
+
* that matches none is known to be unknown before anything is sent to it.
|
|
5
|
+
* The models themselves live with their family: ESCPOS_MODELS, TSPL_MODELS
|
|
6
|
+
* and CAT_MODELS.
|
|
7
|
+
*/
|
|
8
|
+
import type { ClientLike } from './client.js';
|
|
9
|
+
import { type Pace, type ThermalModel, type ThermalTransport } from './thermal.js';
|
|
2
10
|
export type PrinterFamily = 'escpos' | 'tspl' | 'cat';
|
|
3
11
|
export interface CatalogEntry {
|
|
4
12
|
family: PrinterFamily;
|
|
@@ -7,6 +15,18 @@ export interface CatalogEntry {
|
|
|
7
15
|
export declare const PRINTER_CATALOG: CatalogEntry[];
|
|
8
16
|
/** The known printer a Bluetooth name belongs to, longest prefix first across every family. */
|
|
9
17
|
export declare function identifyPrinter(name: string | undefined): CatalogEntry | null;
|
|
18
|
+
/** The known printer behind a USB device: by its vendor and product IDs, then by its product name. */
|
|
19
|
+
export declare function identifyUsbPrinter({ vendorId, productId, productName }: {
|
|
20
|
+
vendorId: number;
|
|
21
|
+
productId: number;
|
|
22
|
+
productName?: string;
|
|
23
|
+
}): CatalogEntry | null;
|
|
24
|
+
/**
|
|
25
|
+
* The client for a thermal printer over a cable link. Cat printers are
|
|
26
|
+
* Bluetooth only, so they get null. `ackTimeoutMs`: how long a label printer
|
|
27
|
+
* waits for its "OK" before asking for its status.
|
|
28
|
+
*/
|
|
29
|
+
export declare function cableClient({ family, model }: CatalogEntry, transport: ThermalTransport, pace: Pace, ackTimeoutMs: number): ClientLike | null;
|
|
10
30
|
/** A kind of printer to pick for one niimai does not recognise. */
|
|
11
31
|
export interface PrinterType extends CatalogEntry {
|
|
12
32
|
id: string;
|
package/dist/client.d.ts
CHANGED
|
@@ -67,9 +67,11 @@ export interface ClientLike {
|
|
|
67
67
|
*/
|
|
68
68
|
unrecognisedAs?(typeId: string | null): void;
|
|
69
69
|
}
|
|
70
|
-
|
|
70
|
+
/** `serial`: a printer on a USB cable that shows up as a serial port, as NIIMBOT printers do. `usb`: one that shows up as a standard USB printer. */
|
|
71
|
+
export type ConnectionKind = 'bluetooth' | 'serial' | 'usb' | 'demo';
|
|
71
72
|
export declare const supportsBluetooth: () => boolean;
|
|
72
73
|
export declare const supportsSerial: () => boolean;
|
|
74
|
+
export declare const supportsUsb: () => boolean;
|
|
73
75
|
export type Platform = 'ios' | 'android' | 'desktop';
|
|
74
76
|
export declare function detectPlatform(ua?: string, touchPoints?: number): Platform;
|
|
75
77
|
export type OperatingSystem = 'ios' | 'android' | 'chromeos' | 'linux' | 'mac' | 'windows' | 'other';
|
|
@@ -77,7 +79,7 @@ export type BrowserName = 'chrome' | 'edge' | 'opera' | 'brave' | 'samsung' | 'b
|
|
|
77
79
|
export interface BrowserInfo {
|
|
78
80
|
os: OperatingSystem;
|
|
79
81
|
browser: BrowserName;
|
|
80
|
-
/** Built on Chromium, so Web Bluetooth
|
|
82
|
+
/** Built on Chromium, so Web Bluetooth, Web Serial and WebUSB can be there. */
|
|
81
83
|
chromium: boolean;
|
|
82
84
|
/** Served over https or from localhost; browsers hide both APIs elsewhere. */
|
|
83
85
|
secure: boolean;
|
|
@@ -98,8 +100,9 @@ export declare function detectBrowser(env?: Partial<BrowserEnv>): BrowserInfo;
|
|
|
98
100
|
* - `ios`: iPhone and iPad browsers, and Bluefy.
|
|
99
101
|
* - `https`: the page has to be served over https.
|
|
100
102
|
* - `browsers`: which browsers work.
|
|
103
|
+
* - `usb`: Windows and Linux hold on to USB printers until told to let the browser have them.
|
|
101
104
|
*/
|
|
102
|
-
export type SetupTopic = 'linux' | 'brave' | 'ios' | 'https' | 'browsers';
|
|
105
|
+
export type SetupTopic = 'linux' | 'brave' | 'ios' | 'https' | 'browsers' | 'usb';
|
|
103
106
|
export interface SupportIssue {
|
|
104
107
|
/** In a few words, what is missing or what to do. */
|
|
105
108
|
reason: string;
|
|
@@ -113,8 +116,8 @@ export declare function supportIssue(kind: ConnectionKind, env?: Partial<Browser
|
|
|
113
116
|
/** supportIssue's reason alone. */
|
|
114
117
|
export declare function unsupportedReason(kind: ConnectionKind, platform?: Platform): string | null;
|
|
115
118
|
/**
|
|
116
|
-
* Errors browsers raise when Bluetooth is there but cannot be used:
|
|
117
|
-
* adapter is off or missing,
|
|
118
|
-
* to point to, or null.
|
|
119
|
+
* Errors browsers raise when Bluetooth or USB is there but cannot be used:
|
|
120
|
+
* the adapter is off or missing, the browser turned the API off, or the
|
|
121
|
+
* system keeps a USB printer for itself. The Help topic to point to, or null.
|
|
119
122
|
*/
|
|
120
123
|
export declare function connectErrorTopic(err: unknown): SetupTopic | null;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/// <reference types="web-bluetooth" preserve="true" />
|
|
2
2
|
/// <reference types="w3c-web-serial" preserve="true" />
|
|
3
|
+
/// <reference types="w3c-web-usb" preserve="true" />
|
|
3
4
|
import type { ClientLike, ConnectionKind } from './client.js';
|
|
4
5
|
import { PrinterService, type ClientFactory } from './service.js';
|
|
5
6
|
/**
|
|
6
7
|
* A client for one kind of connection. Bluetooth finds the printer family
|
|
7
|
-
* from the device the user picks; serial is NIIMBOT only;
|
|
8
|
-
*
|
|
8
|
+
* from the device the user picks; serial is NIIMBOT only; usb is for label
|
|
9
|
+
* and receipt printers that show up as standard USB printers; demo is a
|
|
10
|
+
* printer in memory.
|
|
9
11
|
*/
|
|
10
12
|
export declare function createClient(kind: ConnectionKind): Promise<ClientLike>;
|
|
11
13
|
export interface CreatePrinterOptions {
|
|
@@ -19,15 +21,16 @@ export interface CreatePrinterOptions {
|
|
|
19
21
|
export declare function createPrinter(options?: CreatePrinterOptions): PrinterService;
|
|
20
22
|
export { PrinterService, DEMO_NAME, friendlyError, fitToPrinthead, rotateCanvas, shiftCanvas } from './service.js';
|
|
21
23
|
export type { ClientFactory, PageSource, PrinterState, PrinterStatus, PrintOffset, PrintOptions, Rotation } from './service.js';
|
|
22
|
-
export { connectErrorTopic, detectBrowser, detectPlatform, supportIssue, supportsBluetooth, supportsSerial, unsupportedReason } from './client.js';
|
|
24
|
+
export { connectErrorTopic, detectBrowser, detectPlatform, supportIssue, supportsBluetooth, supportsSerial, supportsUsb, unsupportedReason } from './client.js';
|
|
23
25
|
export type { BrowserEnv, BrowserInfo, BrowserName, ClientLike, ConnectionKind, OperatingSystem, Platform, PrintTaskLike, SetupTopic, SupportIssue } from './client.js';
|
|
24
26
|
export { correctTask, findManualProfile, inkOutsideHead, MANUAL_PROFILES, printheadCrop, printheadMm, resolveProfile } from './profiles.js';
|
|
25
27
|
export type { LabelSize, PrintDirection, PrinterProfile } from './profiles.js';
|
|
26
28
|
export { effectivePaper, labelTypeOf, PAPER_TYPES, paperFromLabelType, paperName } from './paper.js';
|
|
27
29
|
export type { PaperType } from './paper.js';
|
|
28
|
-
export { findPrinterType, identifyPrinter, PRINTER_CATALOG, PRINTER_TYPES } from './catalog.js';
|
|
30
|
+
export { findPrinterType, identifyPrinter, identifyUsbPrinter, PRINTER_CATALOG, PRINTER_TYPES } from './catalog.js';
|
|
29
31
|
export type { CatalogEntry, PrinterFamily, PrinterType } from './catalog.js';
|
|
30
32
|
export { BluetoothPrinter } from './bluetooth.js';
|
|
33
|
+
export { familiesFromDeviceId, parseDeviceId, rememberedUsbPrinters, UsbPrinter, usbTransport, USB_PRINTER_CLASS } from './usb.js';
|
|
31
34
|
export { describeBleError } from './ble.js';
|
|
32
35
|
export { DEMO_META, MockClient } from './mock.js';
|
|
33
36
|
export { modelFor, THERMAL_DEFAULT_SIZE, THERMAL_HEAD_DOTS, THERMAL_HEAD_MM, THERMAL_SIZES, ThermalPrinterClient, webTransport } from './thermal.js';
|
package/dist/libniimai.js
CHANGED
|
@@ -227,7 +227,7 @@ var ThermalPrinterClient = class {
|
|
|
227
227
|
constructor(transport, pace, firstChunk) {
|
|
228
228
|
this.transport = transport;
|
|
229
229
|
this.pace = pace;
|
|
230
|
-
this.chunk = firstChunk;
|
|
230
|
+
this.chunk = transport.chunkBytes ?? firstChunk;
|
|
231
231
|
transport.onDisconnect(() => {
|
|
232
232
|
this.connected = false;
|
|
233
233
|
this.emit("disconnect", {});
|
|
@@ -868,7 +868,8 @@ var DOTS_PER_MM = 8;
|
|
|
868
868
|
var TSPL_MODELS = [{
|
|
869
869
|
prefix: "QR380A",
|
|
870
870
|
confidence: "tested",
|
|
871
|
-
note: "Sold as CC390"
|
|
871
|
+
note: "Sold as CC390",
|
|
872
|
+
usbIds: [[10473, 649]]
|
|
872
873
|
}, {
|
|
873
874
|
prefix: "GP-M322",
|
|
874
875
|
confidence: "medium",
|
|
@@ -1033,13 +1034,6 @@ var TsplPrinterClient = class extends ThermalPrinterClient {
|
|
|
1033
1034
|
}
|
|
1034
1035
|
};
|
|
1035
1036
|
// src/catalog.ts
|
|
1036
|
-
/**
|
|
1037
|
-
* Every printer outside NIIMBOT that libniimai knows, by Bluetooth name, in
|
|
1038
|
-
* one lookup across families. A name matches one family at most, and a name
|
|
1039
|
-
* that matches none is known to be unknown before anything is sent to it.
|
|
1040
|
-
* The models themselves live with their family: ESCPOS_MODELS, TSPL_MODELS
|
|
1041
|
-
* and CAT_MODELS.
|
|
1042
|
-
*/
|
|
1043
1037
|
var PRINTER_CATALOG = [
|
|
1044
1038
|
...ESCPOS_MODELS.map((model) => ({
|
|
1045
1039
|
family: "escpos",
|
|
@@ -1061,6 +1055,20 @@ function identifyPrinter(name) {
|
|
|
1061
1055
|
for (const entry of PRINTER_CATALOG) if (name.startsWith(entry.model.prefix) && entry.model.prefix.length > (best?.model.prefix.length ?? 0)) best = entry;
|
|
1062
1056
|
return best;
|
|
1063
1057
|
}
|
|
1058
|
+
/** The known printer behind a USB device: by its vendor and product IDs, then by its product name. */
|
|
1059
|
+
function identifyUsbPrinter({ vendorId, productId, productName }) {
|
|
1060
|
+
return PRINTER_CATALOG.find((e) => e.model.usbIds?.some(([v, p]) => v === vendorId && p === productId)) ?? identifyPrinter(productName);
|
|
1061
|
+
}
|
|
1062
|
+
/**
|
|
1063
|
+
* The client for a thermal printer over a cable link. Cat printers are
|
|
1064
|
+
* Bluetooth only, so they get null. `ackTimeoutMs`: how long a label printer
|
|
1065
|
+
* waits for its "OK" before asking for its status.
|
|
1066
|
+
*/
|
|
1067
|
+
function cableClient({ family, model }, transport, pace, ackTimeoutMs) {
|
|
1068
|
+
if (family === "tspl") return new TsplPrinterClient(transport, model, pace, ackTimeoutMs);
|
|
1069
|
+
if (family === "escpos") return new EscPosPrinterClient(transport, model, pace);
|
|
1070
|
+
return null;
|
|
1071
|
+
}
|
|
1064
1072
|
/** The kinds of printer an unrecognised one can be set to, alongside NIIMBOT's MANUAL_PROFILES. */
|
|
1065
1073
|
var PRINTER_TYPES = [
|
|
1066
1074
|
{
|
|
@@ -1108,6 +1116,70 @@ var PRINTER_TYPES = [
|
|
|
1108
1116
|
}
|
|
1109
1117
|
];
|
|
1110
1118
|
var findPrinterType = (id) => PRINTER_TYPES.find((t) => t.id === id) ?? null;
|
|
1119
|
+
// src/routed.ts
|
|
1120
|
+
/**
|
|
1121
|
+
* A client that picks the real client when it connects, then passes
|
|
1122
|
+
* everything through to it: the Bluetooth and USB printers behind the
|
|
1123
|
+
* Connect buttons.
|
|
1124
|
+
*/
|
|
1125
|
+
var RoutedClient = class {
|
|
1126
|
+
inner = null;
|
|
1127
|
+
get client() {
|
|
1128
|
+
if (!this.inner) throw new Error("Not connected");
|
|
1129
|
+
return this.inner;
|
|
1130
|
+
}
|
|
1131
|
+
async disconnect() {
|
|
1132
|
+
await this.inner?.disconnect();
|
|
1133
|
+
}
|
|
1134
|
+
isConnected() {
|
|
1135
|
+
return !!this.inner?.isConnected();
|
|
1136
|
+
}
|
|
1137
|
+
on(event, fn) {
|
|
1138
|
+
return this.client.on(event, fn);
|
|
1139
|
+
}
|
|
1140
|
+
off(event, fn) {
|
|
1141
|
+
return this.inner?.off(event, fn);
|
|
1142
|
+
}
|
|
1143
|
+
getPrinterInfo() {
|
|
1144
|
+
return this.inner?.getPrinterInfo() ?? {};
|
|
1145
|
+
}
|
|
1146
|
+
getModelMetadata() {
|
|
1147
|
+
return this.inner?.getModelMetadata();
|
|
1148
|
+
}
|
|
1149
|
+
getPrintTaskType() {
|
|
1150
|
+
return this.inner?.getPrintTaskType();
|
|
1151
|
+
}
|
|
1152
|
+
getRfidInfo() {
|
|
1153
|
+
return this.inner?.getRfidInfo() ?? {};
|
|
1154
|
+
}
|
|
1155
|
+
fetchRfidInfo() {
|
|
1156
|
+
return this.client.fetchRfidInfo();
|
|
1157
|
+
}
|
|
1158
|
+
startHeartbeat() {
|
|
1159
|
+
this.inner?.startHeartbeat();
|
|
1160
|
+
}
|
|
1161
|
+
stopHeartbeat() {
|
|
1162
|
+
this.inner?.stopHeartbeat();
|
|
1163
|
+
}
|
|
1164
|
+
isHeartbeatStarted() {
|
|
1165
|
+
return !!this.inner?.isHeartbeatStarted?.();
|
|
1166
|
+
}
|
|
1167
|
+
get protocol() {
|
|
1168
|
+
return this.client.protocol;
|
|
1169
|
+
}
|
|
1170
|
+
get encodePage() {
|
|
1171
|
+
return this.inner?.encodePage?.bind(this.inner);
|
|
1172
|
+
}
|
|
1173
|
+
get rollKey() {
|
|
1174
|
+
return this.inner?.rollKey?.bind(this.inner);
|
|
1175
|
+
}
|
|
1176
|
+
get feedPaper() {
|
|
1177
|
+
return this.inner?.feedPaper?.bind(this.inner);
|
|
1178
|
+
}
|
|
1179
|
+
get feedsBack() {
|
|
1180
|
+
return this.inner?.feedsBack;
|
|
1181
|
+
}
|
|
1182
|
+
};
|
|
1111
1183
|
// src/bluetooth.ts
|
|
1112
1184
|
/**
|
|
1113
1185
|
* A writable characteristic on one of the serial services budget printers
|
|
@@ -1124,7 +1196,7 @@ async function writeChannel(server, services) {
|
|
|
1124
1196
|
}
|
|
1125
1197
|
return null;
|
|
1126
1198
|
}
|
|
1127
|
-
var PRINTER_TYPE_NAMES = {
|
|
1199
|
+
var PRINTER_TYPE_NAMES$1 = {
|
|
1128
1200
|
escpos: "receipt printer",
|
|
1129
1201
|
tspl: "label printer",
|
|
1130
1202
|
cat: "cat printer"
|
|
@@ -1164,16 +1236,12 @@ function looksNiimbot(lib, name) {
|
|
|
1164
1236
|
* the TSPL client; and everything else the NIIMBOT client exactly as before.
|
|
1165
1237
|
* Known names never overlap, so each printer matches one client at most.
|
|
1166
1238
|
*/
|
|
1167
|
-
var BluetoothPrinter = class {
|
|
1239
|
+
var BluetoothPrinter = class extends RoutedClient {
|
|
1168
1240
|
lib;
|
|
1169
|
-
inner = null;
|
|
1170
1241
|
constructor(lib) {
|
|
1242
|
+
super();
|
|
1171
1243
|
this.lib = lib;
|
|
1172
1244
|
}
|
|
1173
|
-
get client() {
|
|
1174
|
-
if (!this.inner) throw new Error("Not connected");
|
|
1175
|
-
return this.inner;
|
|
1176
|
-
}
|
|
1177
1245
|
/** The kind of printer to treat an unrecognised one as; null leaves it to NIIMBOT. */
|
|
1178
1246
|
fallback = null;
|
|
1179
1247
|
unrecognisedAs(typeId) {
|
|
@@ -1189,7 +1257,7 @@ var BluetoothPrinter = class {
|
|
|
1189
1257
|
const services = (await server.getPrimaryServices().catch(() => [])).map((s) => s.uuid);
|
|
1190
1258
|
this.inner = await thermalClient(device, server, services, entry);
|
|
1191
1259
|
if (this.inner) return this.inner.connect();
|
|
1192
|
-
if (!known) throw new Error(`${device.name ?? "This printer"} does not offer a ${PRINTER_TYPE_NAMES[entry.family]} service`);
|
|
1260
|
+
if (!known) throw new Error(`${device.name ?? "This printer"} does not offer a ${PRINTER_TYPE_NAMES$1[entry.family]} service`);
|
|
1193
1261
|
}
|
|
1194
1262
|
const lib = await this.lib();
|
|
1195
1263
|
this.inner = createBleClient(lib, device);
|
|
@@ -1200,57 +1268,6 @@ var BluetoothPrinter = class {
|
|
|
1200
1268
|
throw new Error(`${device.name ?? "This printer"} did not answer as a NIIMBOT. If it is another kind, pick its type under Advanced and connect again.`);
|
|
1201
1269
|
}
|
|
1202
1270
|
}
|
|
1203
|
-
async disconnect() {
|
|
1204
|
-
await this.inner?.disconnect();
|
|
1205
|
-
}
|
|
1206
|
-
isConnected() {
|
|
1207
|
-
return !!this.inner?.isConnected();
|
|
1208
|
-
}
|
|
1209
|
-
on(event, fn) {
|
|
1210
|
-
return this.client.on(event, fn);
|
|
1211
|
-
}
|
|
1212
|
-
off(event, fn) {
|
|
1213
|
-
return this.inner?.off(event, fn);
|
|
1214
|
-
}
|
|
1215
|
-
getPrinterInfo() {
|
|
1216
|
-
return this.inner?.getPrinterInfo() ?? {};
|
|
1217
|
-
}
|
|
1218
|
-
getModelMetadata() {
|
|
1219
|
-
return this.inner?.getModelMetadata();
|
|
1220
|
-
}
|
|
1221
|
-
getPrintTaskType() {
|
|
1222
|
-
return this.inner?.getPrintTaskType();
|
|
1223
|
-
}
|
|
1224
|
-
getRfidInfo() {
|
|
1225
|
-
return this.inner?.getRfidInfo() ?? {};
|
|
1226
|
-
}
|
|
1227
|
-
fetchRfidInfo() {
|
|
1228
|
-
return this.client.fetchRfidInfo();
|
|
1229
|
-
}
|
|
1230
|
-
startHeartbeat() {
|
|
1231
|
-
this.inner?.startHeartbeat();
|
|
1232
|
-
}
|
|
1233
|
-
stopHeartbeat() {
|
|
1234
|
-
this.inner?.stopHeartbeat();
|
|
1235
|
-
}
|
|
1236
|
-
isHeartbeatStarted() {
|
|
1237
|
-
return !!this.inner?.isHeartbeatStarted?.();
|
|
1238
|
-
}
|
|
1239
|
-
get protocol() {
|
|
1240
|
-
return this.client.protocol;
|
|
1241
|
-
}
|
|
1242
|
-
get encodePage() {
|
|
1243
|
-
return this.inner?.encodePage?.bind(this.inner);
|
|
1244
|
-
}
|
|
1245
|
-
get rollKey() {
|
|
1246
|
-
return this.inner?.rollKey?.bind(this.inner);
|
|
1247
|
-
}
|
|
1248
|
-
get feedPaper() {
|
|
1249
|
-
return this.inner?.feedPaper?.bind(this.inner);
|
|
1250
|
-
}
|
|
1251
|
-
get feedsBack() {
|
|
1252
|
-
return this.inner?.feedsBack;
|
|
1253
|
-
}
|
|
1254
1271
|
};
|
|
1255
1272
|
// src/mock.ts
|
|
1256
1273
|
/** A printer that only exists in memory. Used by the demo mode and the tests. */
|
|
@@ -1621,7 +1638,7 @@ function withTimeout(p, ms) {
|
|
|
1621
1638
|
/** Translates the library's error codes and messages into short, readable ones. */
|
|
1622
1639
|
function friendlyError(err) {
|
|
1623
1640
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1624
|
-
if (/user cancelled|no device selected|chooser/i.test(msg)) return "Connection cancelled";
|
|
1641
|
+
if (/user cancelled|no (device|port) selected|chooser/i.test(msg)) return "Connection cancelled";
|
|
1625
1642
|
if (/timeout waiting for the printer to finish/i.test(msg)) return "The printer did not confirm the print";
|
|
1626
1643
|
if (/timeout/i.test(msg)) return "Printer stopped responding";
|
|
1627
1644
|
if (/lid|cover/i.test(msg)) return "Close the printer lid";
|
|
@@ -1883,6 +1900,12 @@ var PrinterService = class {
|
|
|
1883
1900
|
// src/client.ts
|
|
1884
1901
|
var supportsBluetooth = () => typeof navigator !== "undefined" && "bluetooth" in navigator;
|
|
1885
1902
|
var supportsSerial = () => typeof navigator !== "undefined" && "serial" in navigator;
|
|
1903
|
+
var supportsUsb = () => typeof navigator !== "undefined" && "usb" in navigator;
|
|
1904
|
+
var SUPPORTS = {
|
|
1905
|
+
bluetooth: supportsBluetooth,
|
|
1906
|
+
serial: supportsSerial,
|
|
1907
|
+
usb: supportsUsb
|
|
1908
|
+
};
|
|
1886
1909
|
function detectPlatform(ua = typeof navigator === "undefined" ? "" : navigator.userAgent, touchPoints = typeof navigator === "undefined" ? 0 : navigator.maxTouchPoints) {
|
|
1887
1910
|
if (/iPhone|iPad|iPod/.test(ua) || /Macintosh/.test(ua) && touchPoints > 1) return "ios";
|
|
1888
1911
|
if (/Android/.test(ua)) return "android";
|
|
@@ -1928,7 +1951,7 @@ var BROWSER_NAMES = {
|
|
|
1928
1951
|
*/
|
|
1929
1952
|
function supportIssue(kind, env = {}) {
|
|
1930
1953
|
if (kind === "demo") return null;
|
|
1931
|
-
if (kind
|
|
1954
|
+
if (SUPPORTS[kind]()) return null;
|
|
1932
1955
|
const { os, browser, chromium, secure } = detectBrowser(env);
|
|
1933
1956
|
const bluetooth = kind === "bluetooth";
|
|
1934
1957
|
if (os === "ios") return {
|
|
@@ -1994,36 +2017,182 @@ function unsupportedReason(kind, platform) {
|
|
|
1994
2017
|
return supportIssue(kind, platform ? PLATFORM_ENVS[platform] : {})?.reason ?? null;
|
|
1995
2018
|
}
|
|
1996
2019
|
/**
|
|
1997
|
-
* Errors browsers raise when Bluetooth is there but cannot be used:
|
|
1998
|
-
* adapter is off or missing,
|
|
1999
|
-
* to point to, or null.
|
|
2020
|
+
* Errors browsers raise when Bluetooth or USB is there but cannot be used:
|
|
2021
|
+
* the adapter is off or missing, the browser turned the API off, or the
|
|
2022
|
+
* system keeps a USB printer for itself. The Help topic to point to, or null.
|
|
2000
2023
|
*/
|
|
2001
2024
|
function connectErrorTopic(err) {
|
|
2002
2025
|
const message = err instanceof Error ? err.message : String(err);
|
|
2003
2026
|
if (/globally disabled/i.test(message)) return "brave";
|
|
2027
|
+
if (/claim interface|Access denied|Unable to open device/i.test(message)) return "usb";
|
|
2004
2028
|
if (/adapter not available|Bluetooth adapter|Bluetooth is (turned off|disabled|not available)/i.test(message)) return detectBrowser().os === "linux" ? "linux" : "browsers";
|
|
2005
2029
|
return null;
|
|
2006
2030
|
}
|
|
2031
|
+
// src/usb.ts
|
|
2032
|
+
/**
|
|
2033
|
+
* Label and receipt printers on a USB cable that show up as standard USB
|
|
2034
|
+
* printers (interface class 7), which Web Serial cannot see. They take the
|
|
2035
|
+
* same TSPL or ESC/POS bytes as over Bluetooth, through WebUSB. NIIMBOT
|
|
2036
|
+
* printers show up as serial ports and keep using Web Serial.
|
|
2037
|
+
*/
|
|
2038
|
+
var USB_PRINTER_CLASS = 7;
|
|
2039
|
+
/** USB moves data far faster than Bluetooth and paces itself, so writes are large and back to back. */
|
|
2040
|
+
var USB_PACE = {
|
|
2041
|
+
chunkMs: 0,
|
|
2042
|
+
pauseMs: 100
|
|
2043
|
+
};
|
|
2044
|
+
var USB_CHUNK = 4096;
|
|
2045
|
+
/** Label printers may not send "OK" over USB; a status query after this long tells a fault from a quiet printer. */
|
|
2046
|
+
var USB_ACK_TIMEOUT_MS = 5e3;
|
|
2047
|
+
/**
|
|
2048
|
+
* The fields of an IEEE 1284 device ID, keys in capitals:
|
|
2049
|
+
* "MFG:ACME;COMMAND SET:TSC/ESC/POS;MODEL:CC390;" → { MFG, 'COMMAND SET', MODEL }.
|
|
2050
|
+
*/
|
|
2051
|
+
function parseDeviceId(text) {
|
|
2052
|
+
const fields = {};
|
|
2053
|
+
for (const part of text.split(";")) {
|
|
2054
|
+
const at = part.indexOf(":");
|
|
2055
|
+
if (at > 0) fields[part.slice(0, at).trim().toUpperCase()] = part.slice(at + 1).trim();
|
|
2056
|
+
}
|
|
2057
|
+
return fields;
|
|
2058
|
+
}
|
|
2059
|
+
/** The printer languages a device ID names, TSPL first: label printers often take ESC/POS as well. */
|
|
2060
|
+
function familiesFromDeviceId(text) {
|
|
2061
|
+
const id = parseDeviceId(text);
|
|
2062
|
+
const commands = id.CMD ?? id["COMMAND SET"] ?? "";
|
|
2063
|
+
const families = [];
|
|
2064
|
+
if (/\b(TSPL2?|TSC)\b/i.test(commands)) families.push("tspl");
|
|
2065
|
+
if (/ESC\/?POS|\bEPSON\b/i.test(commands)) families.push("escpos");
|
|
2066
|
+
return families;
|
|
2067
|
+
}
|
|
2068
|
+
var isPrinter = (device) => device.configuration?.interfaces.some((i) => i.alternates.some((a) => a.interfaceClass === 7)) ?? true;
|
|
2069
|
+
/** USB printers this site may already use that are plugged in. */
|
|
2070
|
+
async function rememberedUsbPrinters() {
|
|
2071
|
+
if (!supportsUsb()) return [];
|
|
2072
|
+
return (await navigator.usb.getDevices().catch(() => [])).filter(isPrinter);
|
|
2073
|
+
}
|
|
2074
|
+
/** Opens a USB printer and claims its printer interface. Also reads the printer's device ID. */
|
|
2075
|
+
async function usbTransport(device) {
|
|
2076
|
+
await device.open();
|
|
2077
|
+
if (!device.configuration) await device.selectConfiguration(1);
|
|
2078
|
+
const iface = device.configuration.interfaces.find((i) => i.alternates.some((a) => a.interfaceClass === 7));
|
|
2079
|
+
if (!iface) throw new Error(`${device.productName ?? "This device"} is not a USB printer`);
|
|
2080
|
+
const alt = iface.alternates.find((a) => a.interfaceClass === 7);
|
|
2081
|
+
await device.claimInterface(iface.interfaceNumber);
|
|
2082
|
+
if (alt.alternateSetting !== 0) await device.selectAlternateInterface(iface.interfaceNumber, alt.alternateSetting);
|
|
2083
|
+
const out = alt.endpoints.find((e) => e.direction === "out" && e.type === "bulk");
|
|
2084
|
+
const back = alt.endpoints.find((e) => e.direction === "in" && e.type === "bulk");
|
|
2085
|
+
if (!out) throw new Error(`${device.productName ?? "This printer"} has no way to send it data`);
|
|
2086
|
+
const deviceId = await device.controlTransferIn({
|
|
2087
|
+
requestType: "class",
|
|
2088
|
+
recipient: "interface",
|
|
2089
|
+
request: 0,
|
|
2090
|
+
value: 0,
|
|
2091
|
+
index: iface.interfaceNumber << 8 | alt.alternateSetting
|
|
2092
|
+
}, 1024).then((r) => r.data ? new TextDecoder().decode(new Uint8Array(r.data.buffer, r.data.byteOffset + 2, Math.max(0, r.data.byteLength - 2))) : "").catch(() => "");
|
|
2093
|
+
const notify = [];
|
|
2094
|
+
const gone = [];
|
|
2095
|
+
let open = true;
|
|
2096
|
+
if (back) (async () => {
|
|
2097
|
+
while (open) {
|
|
2098
|
+
const r = await device.transferIn(back.endpointNumber, back.packetSize).catch(() => null);
|
|
2099
|
+
if (!r) break;
|
|
2100
|
+
if (r.data?.byteLength) notify.forEach((fn) => fn(new Uint8Array(r.data.buffer.slice(r.data.byteOffset, r.data.byteOffset + r.data.byteLength))));
|
|
2101
|
+
}
|
|
2102
|
+
})();
|
|
2103
|
+
const onUnplug = (e) => {
|
|
2104
|
+
if (e.device !== device) return;
|
|
2105
|
+
open = false;
|
|
2106
|
+
navigator.usb.removeEventListener("disconnect", onUnplug);
|
|
2107
|
+
gone.forEach((fn) => fn());
|
|
2108
|
+
};
|
|
2109
|
+
navigator.usb.addEventListener("disconnect", onUnplug);
|
|
2110
|
+
return {
|
|
2111
|
+
deviceId,
|
|
2112
|
+
transport: {
|
|
2113
|
+
name: device.productName || void 0,
|
|
2114
|
+
chunkBytes: USB_CHUNK,
|
|
2115
|
+
write: async (chunk) => {
|
|
2116
|
+
if ((await device.transferOut(out.endpointNumber, chunk.slice())).status !== "ok") throw new Error("The printer did not take the data");
|
|
2117
|
+
},
|
|
2118
|
+
onNotify: (fn) => notify.push(fn),
|
|
2119
|
+
onDisconnect: (fn) => gone.push(fn),
|
|
2120
|
+
disconnect: async () => {
|
|
2121
|
+
open = false;
|
|
2122
|
+
navigator.usb.removeEventListener("disconnect", onUnplug);
|
|
2123
|
+
await device.releaseInterface(iface.interfaceNumber).catch(() => {});
|
|
2124
|
+
await device.close().catch(() => {});
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
};
|
|
2128
|
+
}
|
|
2129
|
+
var PRINTER_TYPE_NAMES = {
|
|
2130
|
+
escpos: "receipt printer",
|
|
2131
|
+
tspl: "label printer",
|
|
2132
|
+
cat: "cat printer"
|
|
2133
|
+
};
|
|
2134
|
+
/**
|
|
2135
|
+
* The USB printer behind the USB button for label and receipt printers. A
|
|
2136
|
+
* printer this site already uses connects straight away when it is the only
|
|
2137
|
+
* one plugged in; otherwise the browser lists USB printers. The printer's
|
|
2138
|
+
* language comes from the catalog, then from the type picked under Advanced
|
|
2139
|
+
* when the printer speaks it (or does not say), then from the device ID the
|
|
2140
|
+
* printer reports.
|
|
2141
|
+
*/
|
|
2142
|
+
var UsbPrinter = class extends RoutedClient {
|
|
2143
|
+
fallback = null;
|
|
2144
|
+
unrecognisedAs(typeId) {
|
|
2145
|
+
this.fallback = findPrinterType(typeId);
|
|
2146
|
+
}
|
|
2147
|
+
async connect() {
|
|
2148
|
+
const remembered = await rememberedUsbPrinters();
|
|
2149
|
+
const device = remembered.length === 1 ? remembered[0] : await navigator.usb.requestDevice({ filters: [{ classCode: 7 }] });
|
|
2150
|
+
const { transport, deviceId } = await usbTransport(device);
|
|
2151
|
+
const name = device.productName || "This printer";
|
|
2152
|
+
const families = familiesFromDeviceId(deviceId);
|
|
2153
|
+
const picked = this.fallback && (!families.length || families.includes(this.fallback.family)) ? this.fallback : null;
|
|
2154
|
+
const entry = identifyUsbPrinter(device) ?? picked ?? (families.length ? {
|
|
2155
|
+
family: families[0],
|
|
2156
|
+
model: {
|
|
2157
|
+
prefix: "",
|
|
2158
|
+
confidence: "medium",
|
|
2159
|
+
generic: true
|
|
2160
|
+
}
|
|
2161
|
+
} : null);
|
|
2162
|
+
if (!entry) {
|
|
2163
|
+
await transport.disconnect();
|
|
2164
|
+
throw new Error(`${name} did not say which printer language it speaks. Pick its type under Advanced and connect again.`);
|
|
2165
|
+
}
|
|
2166
|
+
this.inner = cableClient(entry, transport, USB_PACE, USB_ACK_TIMEOUT_MS);
|
|
2167
|
+
if (!this.inner) {
|
|
2168
|
+
await transport.disconnect();
|
|
2169
|
+
throw new Error(`A ${PRINTER_TYPE_NAMES[entry.family]} cannot print over USB`);
|
|
2170
|
+
}
|
|
2171
|
+
return this.inner.connect();
|
|
2172
|
+
}
|
|
2173
|
+
};
|
|
2007
2174
|
// src/index.ts
|
|
2008
2175
|
/**
|
|
2009
2176
|
* libniimai: connect to NIIMBOT, TSPL, ESC/POS and cat printers from the
|
|
2010
|
-
* browser over Web Bluetooth
|
|
2177
|
+
* browser over Web Bluetooth, Web Serial or WebUSB, and print a canvas on them.
|
|
2011
2178
|
*/
|
|
2012
2179
|
var niimbot = () => import("@mmote/niimbluelib");
|
|
2013
2180
|
/**
|
|
2014
2181
|
* A client for one kind of connection. Bluetooth finds the printer family
|
|
2015
|
-
* from the device the user picks; serial is NIIMBOT only;
|
|
2016
|
-
*
|
|
2182
|
+
* from the device the user picks; serial is NIIMBOT only; usb is for label
|
|
2183
|
+
* and receipt printers that show up as standard USB printers; demo is a
|
|
2184
|
+
* printer in memory.
|
|
2017
2185
|
*/
|
|
2018
2186
|
async function createClient(kind) {
|
|
2019
2187
|
if (kind === "demo") return new MockClient();
|
|
2020
2188
|
if (kind === "bluetooth") return new BluetoothPrinter(niimbot);
|
|
2189
|
+
if (kind === "usb") return new UsbPrinter();
|
|
2021
2190
|
return new (await (niimbot())).NiimbotSerialClient();
|
|
2022
2191
|
}
|
|
2023
2192
|
/** A ready printer service: connect, watch its status, print canvases. */
|
|
2024
2193
|
function createPrinter(options = {}) {
|
|
2025
2194
|
return new PrinterService(options.createClient ?? createClient, async (canvas, direction) => (await niimbot()).ImageEncoder.encodeCanvas(canvas, 0, direction));
|
|
2026
2195
|
}
|
|
2027
|
-
export { BluetoothPrinter, CAT_MODELS, CAT_UNSUPPORTED, CatPrinterClient, DEMO_META, DEMO_NAME, ESCPOS_MODELS, EscPosPrinterClient, MANUAL_PROFILES, MockClient, PAPER_TYPES, PRINTER_CATALOG, PRINTER_TYPES, PrinterService, THERMAL_DEFAULT_SIZE, THERMAL_HEAD_DOTS, THERMAL_HEAD_MM, THERMAL_SIZES, TSPL_MODELS, TSPL_SIZES, ThermalPrinterClient, TsplPrinterClient, catFeed, printJob as catJob, catModelFor, connectErrorTopic, correctTask, createClient, createPrinter, describeBleError, detectBrowser, detectPlatform, effectivePaper, escposFeed, escposJob, escposModelFor, findManualProfile, findPrinterType, fitToPrinthead, friendlyError, identifyPrinter, inkOutsideHead, labelTypeOf, modelFor, paperFromLabelType, paperName, printheadCrop, printheadMm, resolveProfile, rotateCanvas, shiftCanvas, supportIssue, supportsBluetooth, supportsSerial, tsplJob, tsplModelFor, unsupportedReason, webTransport };
|
|
2196
|
+
export { BluetoothPrinter, CAT_MODELS, CAT_UNSUPPORTED, CatPrinterClient, DEMO_META, DEMO_NAME, ESCPOS_MODELS, EscPosPrinterClient, MANUAL_PROFILES, MockClient, PAPER_TYPES, PRINTER_CATALOG, PRINTER_TYPES, PrinterService, THERMAL_DEFAULT_SIZE, THERMAL_HEAD_DOTS, THERMAL_HEAD_MM, THERMAL_SIZES, TSPL_MODELS, TSPL_SIZES, ThermalPrinterClient, TsplPrinterClient, USB_PRINTER_CLASS, UsbPrinter, catFeed, printJob as catJob, catModelFor, connectErrorTopic, correctTask, createClient, createPrinter, describeBleError, detectBrowser, detectPlatform, effectivePaper, escposFeed, escposJob, escposModelFor, familiesFromDeviceId, findManualProfile, findPrinterType, fitToPrinthead, friendlyError, identifyPrinter, identifyUsbPrinter, inkOutsideHead, labelTypeOf, modelFor, paperFromLabelType, paperName, parseDeviceId, printheadCrop, printheadMm, rememberedUsbPrinters, resolveProfile, rotateCanvas, shiftCanvas, supportIssue, supportsBluetooth, supportsSerial, supportsUsb, tsplJob, tsplModelFor, unsupportedReason, usbTransport, webTransport };
|
|
2028
2197
|
|
|
2029
2198
|
//# sourceMappingURL=libniimai.js.map
|