@kreiseck/kasseneck-api 0.6.7
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/LICENSE +201 -0
- package/NOTICE +2 -0
- package/README.md +206 -0
- package/dist/cjs/client/api.d.ts +75 -0
- package/dist/cjs/client/api.js +40 -0
- package/dist/cjs/client/auth.d.ts +52 -0
- package/dist/cjs/client/auth.js +72 -0
- package/dist/cjs/client/cashregisters.d.ts +21 -0
- package/dist/cjs/client/cashregisters.js +36 -0
- package/dist/cjs/client/errors.d.ts +159 -0
- package/dist/cjs/client/errors.js +226 -0
- package/dist/cjs/client/index.d.ts +8 -0
- package/dist/cjs/client/index.js +44 -0
- package/dist/cjs/client/receipts.d.ts +245 -0
- package/dist/cjs/client/receipts.js +452 -0
- package/dist/cjs/client/reports.d.ts +43 -0
- package/dist/cjs/client/reports.js +73 -0
- package/dist/cjs/client/status.d.ts +43 -0
- package/dist/cjs/client/status.js +47 -0
- package/dist/cjs/client/transport.d.ts +117 -0
- package/dist/cjs/client/transport.js +312 -0
- package/dist/cjs/enums/credit-card-provider.d.ts +22 -0
- package/dist/cjs/enums/credit-card-provider.js +23 -0
- package/dist/cjs/enums/define-enum.d.ts +15 -0
- package/dist/cjs/enums/define-enum.js +16 -0
- package/dist/cjs/enums/index.d.ts +7 -0
- package/dist/cjs/enums/index.js +17 -0
- package/dist/cjs/enums/keck-payment-method.d.ts +57 -0
- package/dist/cjs/enums/keck-payment-method.js +23 -0
- package/dist/cjs/enums/receipt-type.d.ts +41 -0
- package/dist/cjs/enums/receipt-type.js +18 -0
- package/dist/cjs/enums/stripe-link-mode.d.ts +17 -0
- package/dist/cjs/enums/stripe-link-mode.js +18 -0
- package/dist/cjs/enums/vat-rate.d.ts +40 -0
- package/dist/cjs/enums/vat-rate.js +19 -0
- package/dist/cjs/enums/voucher-action.d.ts +10 -0
- package/dist/cjs/enums/voucher-action.js +11 -0
- package/dist/cjs/enums/voucher-type.d.ts +9 -0
- package/dist/cjs/enums/voucher-type.js +10 -0
- package/dist/cjs/index.d.ts +5 -0
- package/dist/cjs/index.js +97 -0
- package/dist/cjs/kasse/artikel.d.ts +83 -0
- package/dist/cjs/kasse/artikel.js +79 -0
- package/dist/cjs/kasse/client.d.ts +10 -0
- package/dist/cjs/kasse/client.js +38 -0
- package/dist/cjs/kasse/drucker.d.ts +54 -0
- package/dist/cjs/kasse/drucker.js +41 -0
- package/dist/cjs/kasse/index.d.ts +11 -0
- package/dist/cjs/kasse/index.js +38 -0
- package/dist/cjs/kasse/settings.d.ts +115 -0
- package/dist/cjs/kasse/settings.js +62 -0
- package/dist/cjs/models/cancellation.d.ts +51 -0
- package/dist/cjs/models/cancellation.js +45 -0
- package/dist/cjs/models/cashregister.d.ts +77 -0
- package/dist/cjs/models/cashregister.js +53 -0
- package/dist/cjs/models/enum-payload.d.ts +26 -0
- package/dist/cjs/models/enum-payload.js +50 -0
- package/dist/cjs/models/hobex-receipt.d.ts +63 -0
- package/dist/cjs/models/hobex-receipt.js +86 -0
- package/dist/cjs/models/index.d.ts +10 -0
- package/dist/cjs/models/index.js +46 -0
- package/dist/cjs/models/receipt-company.d.ts +71 -0
- package/dist/cjs/models/receipt-company.js +52 -0
- package/dist/cjs/models/receipt-item.d.ts +100 -0
- package/dist/cjs/models/receipt-item.js +108 -0
- package/dist/cjs/models/receipt-summary.d.ts +92 -0
- package/dist/cjs/models/receipt-summary.js +54 -0
- package/dist/cjs/models/receipt.d.ts +108 -0
- package/dist/cjs/models/receipt.js +119 -0
- package/dist/cjs/models/report-month.d.ts +32 -0
- package/dist/cjs/models/report-month.js +65 -0
- package/dist/cjs/models/stripe-url-session.d.ts +18 -0
- package/dist/cjs/models/stripe-url-session.js +20 -0
- package/dist/cjs/models/voucher.d.ts +41 -0
- package/dist/cjs/models/voucher.js +56 -0
- package/dist/cjs/money.d.ts +23 -0
- package/dist/cjs/money.js +35 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/payments/hobex.d.ts +87 -0
- package/dist/cjs/payments/hobex.js +167 -0
- package/dist/cjs/payments/index.d.ts +33 -0
- package/dist/cjs/payments/index.js +42 -0
- package/dist/cjs/payments/stripe.d.ts +61 -0
- package/dist/cjs/payments/stripe.js +157 -0
- package/dist/cjs/printing/escpos.d.ts +219 -0
- package/dist/cjs/printing/escpos.js +636 -0
- package/dist/cjs/printing/index.d.ts +3 -0
- package/dist/cjs/printing/index.js +33 -0
- package/dist/cjs/printing/printable.d.ts +27 -0
- package/dist/cjs/printing/printable.js +90 -0
- package/dist/cjs/printing/webusb.d.ts +89 -0
- package/dist/cjs/printing/webusb.js +110 -0
- package/dist/cjs/react/index.d.ts +46 -0
- package/dist/cjs/react/index.js +51 -0
- package/dist/cjs/receipt/discount.d.ts +12 -0
- package/dist/cjs/receipt/discount.js +54 -0
- package/dist/cjs/receipt/epos.d.ts +53 -0
- package/dist/cjs/receipt/epos.js +95 -0
- package/dist/cjs/receipt/grid.d.ts +47 -0
- package/dist/cjs/receipt/grid.js +122 -0
- package/dist/cjs/receipt/index.d.ts +4 -0
- package/dist/cjs/receipt/index.js +29 -0
- package/dist/cjs/receipt/layout-escpos.d.ts +35 -0
- package/dist/cjs/receipt/layout-escpos.js +67 -0
- package/dist/cjs/receipt/layout.d.ts +180 -0
- package/dist/cjs/receipt/layout.js +594 -0
- package/dist/cjs/register/index.d.ts +51 -0
- package/dist/cjs/register/index.js +61 -0
- package/dist/cjs/register/pairing.d.ts +248 -0
- package/dist/cjs/register/pairing.js +279 -0
- package/dist/cjs/register/session.d.ts +37 -0
- package/dist/cjs/register/session.js +52 -0
- package/dist/cjs/vienna-time.d.ts +23 -0
- package/dist/cjs/vienna-time.js +114 -0
- package/dist/esm/client/api.d.ts +75 -0
- package/dist/esm/client/api.js +37 -0
- package/dist/esm/client/auth.d.ts +52 -0
- package/dist/esm/client/auth.js +68 -0
- package/dist/esm/client/cashregisters.d.ts +21 -0
- package/dist/esm/client/cashregisters.js +33 -0
- package/dist/esm/client/errors.d.ts +159 -0
- package/dist/esm/client/errors.js +212 -0
- package/dist/esm/client/index.d.ts +8 -0
- package/dist/esm/client/index.js +8 -0
- package/dist/esm/client/receipts.d.ts +245 -0
- package/dist/esm/client/receipts.js +438 -0
- package/dist/esm/client/reports.d.ts +43 -0
- package/dist/esm/client/reports.js +69 -0
- package/dist/esm/client/status.d.ts +43 -0
- package/dist/esm/client/status.js +43 -0
- package/dist/esm/client/transport.d.ts +117 -0
- package/dist/esm/client/transport.js +307 -0
- package/dist/esm/enums/credit-card-provider.d.ts +22 -0
- package/dist/esm/enums/credit-card-provider.js +20 -0
- package/dist/esm/enums/define-enum.d.ts +15 -0
- package/dist/esm/enums/define-enum.js +13 -0
- package/dist/esm/enums/index.d.ts +7 -0
- package/dist/esm/enums/index.js +7 -0
- package/dist/esm/enums/keck-payment-method.d.ts +57 -0
- package/dist/esm/enums/keck-payment-method.js +20 -0
- package/dist/esm/enums/receipt-type.d.ts +41 -0
- package/dist/esm/enums/receipt-type.js +15 -0
- package/dist/esm/enums/stripe-link-mode.d.ts +17 -0
- package/dist/esm/enums/stripe-link-mode.js +15 -0
- package/dist/esm/enums/vat-rate.d.ts +40 -0
- package/dist/esm/enums/vat-rate.js +16 -0
- package/dist/esm/enums/voucher-action.d.ts +10 -0
- package/dist/esm/enums/voucher-action.js +8 -0
- package/dist/esm/enums/voucher-type.d.ts +9 -0
- package/dist/esm/enums/voucher-type.js +7 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/kasse/artikel.d.ts +83 -0
- package/dist/esm/kasse/artikel.js +70 -0
- package/dist/esm/kasse/client.d.ts +10 -0
- package/dist/esm/kasse/client.js +33 -0
- package/dist/esm/kasse/drucker.d.ts +54 -0
- package/dist/esm/kasse/drucker.js +36 -0
- package/dist/esm/kasse/index.d.ts +11 -0
- package/dist/esm/kasse/index.js +13 -0
- package/dist/esm/kasse/settings.d.ts +115 -0
- package/dist/esm/kasse/settings.js +58 -0
- package/dist/esm/models/cancellation.d.ts +51 -0
- package/dist/esm/models/cancellation.js +40 -0
- package/dist/esm/models/cashregister.d.ts +77 -0
- package/dist/esm/models/cashregister.js +50 -0
- package/dist/esm/models/enum-payload.d.ts +26 -0
- package/dist/esm/models/enum-payload.js +44 -0
- package/dist/esm/models/hobex-receipt.d.ts +63 -0
- package/dist/esm/models/hobex-receipt.js +80 -0
- package/dist/esm/models/index.d.ts +10 -0
- package/dist/esm/models/index.js +10 -0
- package/dist/esm/models/receipt-company.d.ts +71 -0
- package/dist/esm/models/receipt-company.js +48 -0
- package/dist/esm/models/receipt-item.d.ts +100 -0
- package/dist/esm/models/receipt-item.js +101 -0
- package/dist/esm/models/receipt-summary.d.ts +92 -0
- package/dist/esm/models/receipt-summary.js +49 -0
- package/dist/esm/models/receipt.d.ts +108 -0
- package/dist/esm/models/receipt.js +113 -0
- package/dist/esm/models/report-month.d.ts +32 -0
- package/dist/esm/models/report-month.js +58 -0
- package/dist/esm/models/stripe-url-session.d.ts +18 -0
- package/dist/esm/models/stripe-url-session.js +16 -0
- package/dist/esm/models/voucher.d.ts +41 -0
- package/dist/esm/models/voucher.js +51 -0
- package/dist/esm/money.d.ts +23 -0
- package/dist/esm/money.js +31 -0
- package/dist/esm/payments/hobex.d.ts +87 -0
- package/dist/esm/payments/hobex.js +162 -0
- package/dist/esm/payments/index.d.ts +33 -0
- package/dist/esm/payments/index.js +33 -0
- package/dist/esm/payments/stripe.d.ts +61 -0
- package/dist/esm/payments/stripe.js +153 -0
- package/dist/esm/printing/escpos.d.ts +219 -0
- package/dist/esm/printing/escpos.js +616 -0
- package/dist/esm/printing/index.d.ts +3 -0
- package/dist/esm/printing/index.js +3 -0
- package/dist/esm/printing/printable.d.ts +27 -0
- package/dist/esm/printing/printable.js +87 -0
- package/dist/esm/printing/webusb.d.ts +89 -0
- package/dist/esm/printing/webusb.js +101 -0
- package/dist/esm/react/index.d.ts +46 -0
- package/dist/esm/react/index.js +47 -0
- package/dist/esm/receipt/discount.d.ts +12 -0
- package/dist/esm/receipt/discount.js +51 -0
- package/dist/esm/receipt/epos.d.ts +53 -0
- package/dist/esm/receipt/epos.js +86 -0
- package/dist/esm/receipt/grid.d.ts +47 -0
- package/dist/esm/receipt/grid.js +116 -0
- package/dist/esm/receipt/index.d.ts +4 -0
- package/dist/esm/receipt/index.js +4 -0
- package/dist/esm/receipt/layout-escpos.d.ts +35 -0
- package/dist/esm/receipt/layout-escpos.js +64 -0
- package/dist/esm/receipt/layout.d.ts +180 -0
- package/dist/esm/receipt/layout.js +583 -0
- package/dist/esm/register/index.d.ts +51 -0
- package/dist/esm/register/index.js +51 -0
- package/dist/esm/register/pairing.d.ts +248 -0
- package/dist/esm/register/pairing.js +270 -0
- package/dist/esm/register/session.d.ts +37 -0
- package/dist/esm/register/session.js +48 -0
- package/dist/esm/vienna-time.d.ts +23 -0
- package/dist/esm/vienna-time.js +110 -0
- package/fixtures/belege/langer-artikelname.json +43 -0
- package/fixtures/belege/null-ausfall.json +41 -0
- package/fixtures/belege/null-jahr.json +41 -0
- package/fixtures/belege/null-monat.json +41 -0
- package/fixtures/belege/null-pruef.json +41 -0
- package/fixtures/belege/null-schluss.json +41 -0
- package/fixtures/belege/null-start.json +40 -0
- package/fixtures/belege/rabattzeilen.json +61 -0
- package/fixtures/belege/signaturausfall-verkauf.json +49 -0
- package/fixtures/belege/storno-teil.json +48 -0
- package/fixtures/belege/storno-voll.json +54 -0
- package/fixtures/belege/testkasse-verkauf.json +50 -0
- package/fixtures/belege/testsignatur-verkauf.json +50 -0
- package/fixtures/belege/training.json +49 -0
- package/fixtures/belege/verkauf-bar.json +49 -0
- package/fixtures/belege/verkauf-karte.json +49 -0
- package/fixtures/belege/verkauf-kleinunternehmer.json +42 -0
- package/fixtures/erwartet/langer-artikelname.grid32.txt +25 -0
- package/fixtures/erwartet/langer-artikelname.grid48.txt +24 -0
- package/fixtures/erwartet/langer-artikelname.lines.json +216 -0
- package/fixtures/erwartet/null-ausfall.grid32.txt +28 -0
- package/fixtures/erwartet/null-ausfall.grid48.txt +25 -0
- package/fixtures/erwartet/null-ausfall.lines.json +220 -0
- package/fixtures/erwartet/null-jahr.grid32.txt +29 -0
- package/fixtures/erwartet/null-jahr.grid48.txt +25 -0
- package/fixtures/erwartet/null-jahr.lines.json +220 -0
- package/fixtures/erwartet/null-monat.grid32.txt +28 -0
- package/fixtures/erwartet/null-monat.grid48.txt +25 -0
- package/fixtures/erwartet/null-monat.lines.json +220 -0
- package/fixtures/erwartet/null-pruef.grid32.txt +28 -0
- package/fixtures/erwartet/null-pruef.grid48.txt +25 -0
- package/fixtures/erwartet/null-pruef.lines.json +220 -0
- package/fixtures/erwartet/null-schluss.grid32.txt +28 -0
- package/fixtures/erwartet/null-schluss.grid48.txt +25 -0
- package/fixtures/erwartet/null-schluss.lines.json +220 -0
- package/fixtures/erwartet/null-start.grid32.txt +28 -0
- package/fixtures/erwartet/null-start.grid48.txt +25 -0
- package/fixtures/erwartet/null-start.lines.json +220 -0
- package/fixtures/erwartet/rabattzeilen.grid32.txt +27 -0
- package/fixtures/erwartet/rabattzeilen.grid48.txt +26 -0
- package/fixtures/erwartet/rabattzeilen.lines.json +286 -0
- package/fixtures/erwartet/signaturausfall-verkauf.grid32.txt +28 -0
- package/fixtures/erwartet/signaturausfall-verkauf.grid48.txt +26 -0
- package/fixtures/erwartet/signaturausfall-verkauf.lines.json +266 -0
- package/fixtures/erwartet/storno-teil.grid32.txt +27 -0
- package/fixtures/erwartet/storno-teil.grid48.txt +26 -0
- package/fixtures/erwartet/storno-teil.lines.json +237 -0
- package/fixtures/erwartet/storno-voll.grid32.txt +29 -0
- package/fixtures/erwartet/storno-voll.grid48.txt +28 -0
- package/fixtures/erwartet/storno-voll.lines.json +277 -0
- package/fixtures/erwartet/testkasse-verkauf.grid32.txt +28 -0
- package/fixtures/erwartet/testkasse-verkauf.grid48.txt +27 -0
- package/fixtures/erwartet/testkasse-verkauf.lines.json +270 -0
- package/fixtures/erwartet/testsignatur-verkauf.grid32.txt +30 -0
- package/fixtures/erwartet/testsignatur-verkauf.grid48.txt +27 -0
- package/fixtures/erwartet/testsignatur-verkauf.lines.json +270 -0
- package/fixtures/erwartet/training.grid32.txt +33 -0
- package/fixtures/erwartet/training.grid48.txt +30 -0
- package/fixtures/erwartet/training.lines.json +277 -0
- package/fixtures/erwartet/verkauf-bar.grid32.txt +25 -0
- package/fixtures/erwartet/verkauf-bar.grid48.txt +24 -0
- package/fixtures/erwartet/verkauf-bar.lines.json +256 -0
- package/fixtures/erwartet/verkauf-karte.grid32.txt +25 -0
- package/fixtures/erwartet/verkauf-karte.grid48.txt +24 -0
- package/fixtures/erwartet/verkauf-karte.lines.json +256 -0
- package/fixtures/erwartet/verkauf-kleinunternehmer.grid32.txt +26 -0
- package/fixtures/erwartet/verkauf-kleinunternehmer.grid48.txt +25 -0
- package/fixtures/erwartet/verkauf-kleinunternehmer.lines.json +226 -0
- package/fixtures/manifest.json +107 -0
- package/package.json +135 -0
|
@@ -0,0 +1,636 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ESC/POS-Bytefolgen fuer Bondrucker — Zwilling von
|
|
4
|
+
* `kasseneck_api/lib/src/printing/escpos/` (Flutter).
|
|
5
|
+
*
|
|
6
|
+
* Dieses Modul erzeugt **nur Bytes**. Es kennt keinen Transport: kein
|
|
7
|
+
* Bluetooth, kein WLAN, kein USB, keine Verbindung. Wer die Bytes wohin
|
|
8
|
+
* schickt, entscheidet der Aufrufer.
|
|
9
|
+
*
|
|
10
|
+
* Die Steuerbefehle sind wortwoertlich aus `commands.dart`, `generator.dart`
|
|
11
|
+
* und `qrcode.dart` uebernommen. Bei ESC/POS zaehlt jedes Byte: ein
|
|
12
|
+
* "ungefaehr richtiger" Befehl druckt Unsinn oder gar nichts. Reihenfolge und
|
|
13
|
+
* Bytefolge deshalb nicht anpassen, ohne die Erwartungswerte in
|
|
14
|
+
* `test/escpos.test.ts` gegen das Flutter-Vorbild neu abzugleichen.
|
|
15
|
+
*
|
|
16
|
+
* **Zeichenkodierung.** Bondrucker sprechen kein UTF-8, sondern eine
|
|
17
|
+
* Codepage. Dieses Modul kodiert Text wie das Vorbild nach Latin-1 (ein Byte
|
|
18
|
+
* je Zeichen) und meldet dem Drucker dazu die passende Codepage ueber
|
|
19
|
+
* `ESC t n`. Vorgabe ist CP1252: dort stehen alle deutschen Umlaute an
|
|
20
|
+
* denselben Stellen wie in Latin-1, "ä" ist also genau 0xE4 — ein Byte, nicht
|
|
21
|
+
* zwei. Waeren es zwei (UTF-8), verschoeben sich zusaetzlich alle
|
|
22
|
+
* Spaltenbreiten, weil die Spaltenrechnung mit Byte-Laengen arbeitet.
|
|
23
|
+
* CP437 ist ebenfalls waehlbar — manche (Bluetooth-)Drucker ignorieren
|
|
24
|
+
* `ESC t 16` und bleiben in CP437; dann werden die Umlaute auf ihre
|
|
25
|
+
* CP437-Plaetze umkodiert (ä = 0x84, ü = 0x81, ß = 0xE1, ...). Zeichen ohne
|
|
26
|
+
* CP437-Platz werden zu `?` — weiterhin ein Byte je Zeichen.
|
|
27
|
+
*
|
|
28
|
+
* Nicht enthalten (bewusst): Rasterbilder/Logos, Capability-Profile einzelner
|
|
29
|
+
* Druckermodelle, Kassenlade, 1D-Barcodes.
|
|
30
|
+
*/
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
exports.encodeEscPosText = encodeEscPosText;
|
|
33
|
+
exports.escPosMaxCharsPerLine = escPosMaxCharsPerLine;
|
|
34
|
+
exports.createEscPosDocument = createEscPosDocument;
|
|
35
|
+
exports.escPosBytes = escPosBytes;
|
|
36
|
+
exports.escPosReset = escPosReset;
|
|
37
|
+
exports.escPosSetGlobalCodeTable = escPosSetGlobalCodeTable;
|
|
38
|
+
exports.escPosSetGlobalFont = escPosSetGlobalFont;
|
|
39
|
+
exports.escPosSetStyles = escPosSetStyles;
|
|
40
|
+
exports.escPosWortzeilen = escPosWortzeilen;
|
|
41
|
+
exports.wortzeilenText = wortzeilenText;
|
|
42
|
+
exports.escPosText = escPosText;
|
|
43
|
+
exports.escPosEmptyLines = escPosEmptyLines;
|
|
44
|
+
exports.escPosFeed = escPosFeed;
|
|
45
|
+
exports.escPosCut = escPosCut;
|
|
46
|
+
exports.escPosHr = escPosHr;
|
|
47
|
+
exports.escPosRow = escPosRow;
|
|
48
|
+
exports.qrCodeBytes = qrCodeBytes;
|
|
49
|
+
exports.escPosQrCode = escPosQrCode;
|
|
50
|
+
// -------------------------------------------------------------- Befehlsbytes
|
|
51
|
+
// Wortwoertlich aus commands.dart. Die Zahlen sind ASCII-Codes der dortigen
|
|
52
|
+
// Zeichenketten: cCutFull = '$gs' + 'V0' ist GS 0x56 0x30 — die Ziffer '0',
|
|
53
|
+
// nicht der Nullwert.
|
|
54
|
+
const ESC = 0x1b;
|
|
55
|
+
const GS = 0x1d;
|
|
56
|
+
const FS = 0x1c;
|
|
57
|
+
const C_INIT = [ESC, 0x40]; // ESC @
|
|
58
|
+
const C_CUT_FULL = [GS, 0x56, 0x30]; // GS V '0'
|
|
59
|
+
const C_CUT_PART = [GS, 0x56, 0x31]; // GS V '1'
|
|
60
|
+
const C_REVERSE_ON = [GS, 0x42, 0x01]; // GS B 1
|
|
61
|
+
const C_REVERSE_OFF = [GS, 0x42, 0x00]; // GS B 0
|
|
62
|
+
const C_SIZE = [GS, 0x21]; // GS ! n
|
|
63
|
+
const C_UNDERLINE_OFF = [ESC, 0x2d, 0x00]; // ESC - 0
|
|
64
|
+
const C_UNDERLINE_1DOT = [ESC, 0x2d, 0x01]; // ESC - 1
|
|
65
|
+
const C_BOLD_ON = [ESC, 0x45, 0x01]; // ESC E 1
|
|
66
|
+
const C_BOLD_OFF = [ESC, 0x45, 0x00]; // ESC E 0
|
|
67
|
+
const C_FONT_A = [ESC, 0x4d, 0x00]; // ESC M 0
|
|
68
|
+
const C_FONT_B = [ESC, 0x4d, 0x01]; // ESC M 1
|
|
69
|
+
const C_TURN90_ON = [ESC, 0x56, 0x01]; // ESC V 1
|
|
70
|
+
const C_TURN90_OFF = [ESC, 0x56, 0x00]; // ESC V 0
|
|
71
|
+
const C_CODE_TABLE = [ESC, 0x74]; // ESC t n
|
|
72
|
+
const C_KANJI_OFF = [FS, 0x2e]; // FS .
|
|
73
|
+
const C_ALIGN_LEFT = [ESC, 0x61, 0x30]; // ESC a '0'
|
|
74
|
+
const C_ALIGN_CENTER = [ESC, 0x61, 0x31]; // ESC a '1'
|
|
75
|
+
const C_ALIGN_RIGHT = [ESC, 0x61, 0x32]; // ESC a '2'
|
|
76
|
+
const C_POS = [ESC, 0x24]; // ESC $ nL nH
|
|
77
|
+
const C_FEED_N = [ESC, 0x64]; // ESC d n
|
|
78
|
+
const C_QR_HEADER = [GS, 0x28, 0x6b]; // GS ( k
|
|
79
|
+
const ZEILENUMBRUCH = 0x0a;
|
|
80
|
+
/** Codepage-Nummern fuer `ESC t n` — aus capability_profile.dart. */
|
|
81
|
+
const CODEPAGE_ID = { CP437: 0, CP1252: 16 };
|
|
82
|
+
/** Korrekturstufen fuer GS ( k Funktion 169 — aus qrcode.dart. */
|
|
83
|
+
const QR_KORREKTUR = { L: 48, M: 49, Q: 50, H: 51 };
|
|
84
|
+
/** Druckbreite in Punkten je Papierformat — aus enums.dart (EscPaperSize.width). */
|
|
85
|
+
const PAPIER_BREITE = { mm58: 372, mm80: 558 };
|
|
86
|
+
/** Zeichen je Zeile nach Papier und Schrift — aus generator.dart. */
|
|
87
|
+
const ZEICHEN_JE_ZEILE = {
|
|
88
|
+
mm58: { fontA: 32, fontB: 42 },
|
|
89
|
+
mm80: { fontA: 48, fontB: 64 },
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Zeichen, die das Vorbild vor dem Kodieren ersetzt (generator.dart `_encode`).
|
|
93
|
+
*
|
|
94
|
+
* **Eine bewusste Abweichung:** Fuer `•` sagt generator.dart `.`,
|
|
95
|
+
* print_paper.dart (portiert als `escPosPrintableText`) dagegen `*`. In Darts
|
|
96
|
+
* eigener Kette faellt das nie auf, weil print_paper vor dem Erzeuger ersetzt
|
|
97
|
+
* und der Erzeuger den Punkt nie zu sehen bekommt — die gedruckte Antwort ist
|
|
98
|
+
* dort also `*`. Ein Verbraucher dieses Pakets kann `escPosText` aber auch
|
|
99
|
+
* direkt aufrufen, und dann duerfen nicht zwei Zeichen fuer dasselbe Zeichen
|
|
100
|
+
* herauskommen. Deshalb gilt hier dieselbe Antwort wie dort.
|
|
101
|
+
*/
|
|
102
|
+
const ZEICHEN_ERSATZ = [
|
|
103
|
+
['’', "'"], // typografisches Apostroph
|
|
104
|
+
['´', "'"], // Akut
|
|
105
|
+
['•', '*'], // Aufzaehlungspunkt (siehe Kommentar oben)
|
|
106
|
+
];
|
|
107
|
+
// ------------------------------------------------------------------ Helfer
|
|
108
|
+
function anhaengen(doc, bytes) {
|
|
109
|
+
const ziel = doc.bytes;
|
|
110
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
111
|
+
ziel.push(bytes[i]);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/** Dart rundet .5 vom Nullpunkt weg; JS rundet dort Richtung +unendlich. */
|
|
115
|
+
function runden(wert) {
|
|
116
|
+
return wert < 0 ? -Math.round(-wert) : Math.round(wert);
|
|
117
|
+
}
|
|
118
|
+
function istGanzzahl(wert) {
|
|
119
|
+
return typeof wert === 'number' && Number.isInteger(wert);
|
|
120
|
+
}
|
|
121
|
+
/** Latin-1 ohne Ersetzungen — so kodiert qrcode.dart die QR-Nutzlast. */
|
|
122
|
+
function latin1(text) {
|
|
123
|
+
const bytes = new Uint8Array(text.length);
|
|
124
|
+
for (let i = 0; i < text.length; i++) {
|
|
125
|
+
const code = text.charCodeAt(i);
|
|
126
|
+
if (code > 0xff) {
|
|
127
|
+
const stelle = code.toString(16).toUpperCase().padStart(4, '0');
|
|
128
|
+
throw new Error(`Zeichen "${text.charAt(i)}" (U+${stelle}) an Position ${i} laesst sich nicht ` +
|
|
129
|
+
'in Latin-1 drucken. Text vor der Ausgabe ersetzen ' +
|
|
130
|
+
'(Bondrucker koennen nur eine Ein-Byte-Codepage).');
|
|
131
|
+
}
|
|
132
|
+
bytes[i] = code;
|
|
133
|
+
}
|
|
134
|
+
return bytes;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Kodiert Text so, wie ihn der Drucker erwartet: ein Byte je Zeichen nach
|
|
138
|
+
* Latin-1, vorher die vier Zeichenersetzungen des Vorbilds. Ein Umlaut wird
|
|
139
|
+
* damit zu genau einem Byte — Voraussetzung dafuer, dass die Spaltenrechnung
|
|
140
|
+
* stimmt.
|
|
141
|
+
*/
|
|
142
|
+
function encodeEscPosText(text, codeTable = 'CP1252') {
|
|
143
|
+
let aufbereitet = text;
|
|
144
|
+
for (const [von, nach] of ZEICHEN_ERSATZ) {
|
|
145
|
+
aufbereitet = aufbereitet.split(von).join(nach);
|
|
146
|
+
}
|
|
147
|
+
const bytes = latin1(aufbereitet);
|
|
148
|
+
if (codeTable !== 'CP437')
|
|
149
|
+
return bytes;
|
|
150
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
151
|
+
const b = bytes[i] ?? 0;
|
|
152
|
+
if (b >= 0x80)
|
|
153
|
+
bytes[i] = CP437_AUS_LATIN1.get(b) ?? 0x3f;
|
|
154
|
+
}
|
|
155
|
+
return bytes;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Latin-1-Byte -> CP437-Byte fuer die Zeichen, die CP437 kennt (deutsche
|
|
159
|
+
* Umlaute, ß, westeuropaeische Akzente, Waehrungs-/Sonderzeichen). Alles
|
|
160
|
+
* andere ab 0x80 hat in CP437 keinen Platz und wird zu "?".
|
|
161
|
+
*/
|
|
162
|
+
const CP437_AUS_LATIN1 = new Map([
|
|
163
|
+
[0xc7, 0x80], [0xfc, 0x81], [0xe9, 0x82], [0xe2, 0x83], [0xe4, 0x84], [0xe0, 0x85], [0xe5, 0x86], [0xe7, 0x87],
|
|
164
|
+
[0xea, 0x88], [0xeb, 0x89], [0xe8, 0x8a], [0xef, 0x8b], [0xee, 0x8c], [0xec, 0x8d], [0xc4, 0x8e], [0xc5, 0x8f],
|
|
165
|
+
[0xc9, 0x90], [0xe6, 0x91], [0xc6, 0x92], [0xf4, 0x93], [0xf6, 0x94], [0xf2, 0x95], [0xfb, 0x96], [0xf9, 0x97],
|
|
166
|
+
[0xff, 0x98], [0xd6, 0x99], [0xdc, 0x9a], [0xa2, 0x9b], [0xa3, 0x9c], [0xa5, 0x9d], [0xe1, 0xa0], [0xed, 0xa1],
|
|
167
|
+
[0xf3, 0xa2], [0xfa, 0xa3], [0xf1, 0xa4], [0xd1, 0xa5], [0xaa, 0xa6], [0xba, 0xa7], [0xbf, 0xa8], [0xac, 0xaa],
|
|
168
|
+
[0xbd, 0xab], [0xbc, 0xac], [0xa1, 0xad], [0xab, 0xae], [0xbb, 0xaf], [0xdf, 0xe1], [0xb5, 0xe6], [0xb1, 0xf1],
|
|
169
|
+
[0xf7, 0xf6], [0xb0, 0xf8], [0xb7, 0xfa], [0xb2, 0xfd], [0xa0, 0xff],
|
|
170
|
+
]);
|
|
171
|
+
/** Zeichen je Zeile fuer Papier und Schrift (`fontA`, wenn nichts gesetzt ist). */
|
|
172
|
+
function escPosMaxCharsPerLine(paperSize, font) {
|
|
173
|
+
const breiten = ZEICHEN_JE_ZEILE[paperSize];
|
|
174
|
+
if (breiten === undefined) {
|
|
175
|
+
throw new Error(`Unbekannte Papierbreite: ${String(paperSize)}`);
|
|
176
|
+
}
|
|
177
|
+
return font === 'fontB' ? breiten.fontB : breiten.fontA;
|
|
178
|
+
}
|
|
179
|
+
function vollstaendigeStile(styles = {}) {
|
|
180
|
+
return {
|
|
181
|
+
bold: styles.bold ?? false,
|
|
182
|
+
reverse: styles.reverse ?? false,
|
|
183
|
+
underline: styles.underline ?? false,
|
|
184
|
+
turn90: styles.turn90 ?? false,
|
|
185
|
+
align: styles.align ?? 'left',
|
|
186
|
+
height: styles.height ?? 1,
|
|
187
|
+
width: styles.width ?? 1,
|
|
188
|
+
fontType: styles.fontType ?? null,
|
|
189
|
+
codeTable: styles.codeTable ?? null,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
/** GS ! n: obere vier Bit = Breite, untere vier = Hoehe (enums.dart decSize). */
|
|
193
|
+
function groessenByte(height, width) {
|
|
194
|
+
return 16 * (width - 1) + (height - 1);
|
|
195
|
+
}
|
|
196
|
+
function zeichenProZeile(doc, stile) {
|
|
197
|
+
if (stile.fontType !== null)
|
|
198
|
+
return escPosMaxCharsPerLine(doc.paperSize, stile.fontType);
|
|
199
|
+
return doc.maxCharsPerLine ?? escPosMaxCharsPerLine(doc.paperSize, doc.styles.fontType);
|
|
200
|
+
}
|
|
201
|
+
/** Breite eines Zeichens in Punkten, inklusive Vergroesserungsfaktor. */
|
|
202
|
+
function zeichenBreite(doc, stile) {
|
|
203
|
+
const proZeile = zeichenProZeile(doc, stile);
|
|
204
|
+
return (PAPIER_BREITE[doc.paperSize] / proZeile) * stile.width;
|
|
205
|
+
}
|
|
206
|
+
/** Linker Rand eines Zwoelftel-Rasterindex in Punkten. */
|
|
207
|
+
function spaltenPosition(doc, spaltenIndex) {
|
|
208
|
+
const breite = PAPIER_BREITE[doc.paperSize];
|
|
209
|
+
return spaltenIndex === 0 ? 0 : (breite * spaltenIndex) / 12 - 1;
|
|
210
|
+
}
|
|
211
|
+
// ------------------------------------------------------------- oeffentlich
|
|
212
|
+
/** Legt einen leeren Bytepuffer an. Der erste Befehl ist ueblicherweise `escPosReset`. */
|
|
213
|
+
function createEscPosDocument(options = {}) {
|
|
214
|
+
const paperSize = options.paperSize ?? 'mm58';
|
|
215
|
+
if (PAPIER_BREITE[paperSize] === undefined) {
|
|
216
|
+
throw new Error(`Unbekannte Papierbreite: ${String(paperSize)}`);
|
|
217
|
+
}
|
|
218
|
+
const codeTable = options.codeTable === undefined ? 'CP1252' : options.codeTable;
|
|
219
|
+
if (codeTable !== null && CODEPAGE_ID[codeTable] === undefined) {
|
|
220
|
+
throw new Error(`Unbekannte Codepage: ${String(codeTable)}`);
|
|
221
|
+
}
|
|
222
|
+
const spaceBetweenRows = options.spaceBetweenRows ?? 5;
|
|
223
|
+
if (!istGanzzahl(spaceBetweenRows) || spaceBetweenRows < 0) {
|
|
224
|
+
throw new Error('spaceBetweenRows muss eine Ganzzahl >= 0 sein');
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
paperSize,
|
|
228
|
+
spaceBetweenRows,
|
|
229
|
+
bytes: [],
|
|
230
|
+
globalCodeTable: codeTable,
|
|
231
|
+
globalFont: null,
|
|
232
|
+
maxCharsPerLine: null,
|
|
233
|
+
styles: vollstaendigeStile(),
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
/** Die bisher erzeugten Bytes als Kopie. */
|
|
237
|
+
function escPosBytes(doc) {
|
|
238
|
+
return Uint8Array.from(doc.bytes);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* `ESC @`: Drucker initialisieren und den gemerkten Stil verwerfen. Danach
|
|
242
|
+
* werden globale Codepage und Schrift erneut gesendet — der Drucker vergisst
|
|
243
|
+
* sie beim Initialisieren.
|
|
244
|
+
*/
|
|
245
|
+
function escPosReset(doc) {
|
|
246
|
+
anhaengen(doc, C_INIT);
|
|
247
|
+
doc.styles = vollstaendigeStile();
|
|
248
|
+
escPosSetGlobalCodeTable(doc, doc.globalCodeTable);
|
|
249
|
+
escPosSetGlobalFont(doc, doc.globalFont);
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* `ESC t n`: Codepage waehlen. Sie gilt bis zum naechsten `escPosReset` und
|
|
253
|
+
* wird von diesem erneut gesendet. `null` schaltet die Vorgabe ab; dann
|
|
254
|
+
* bleibt die Codepage des Druckers stehen und Umlaute werden unlesbar.
|
|
255
|
+
*/
|
|
256
|
+
function escPosSetGlobalCodeTable(doc, codeTable) {
|
|
257
|
+
if (codeTable !== null && CODEPAGE_ID[codeTable] === undefined) {
|
|
258
|
+
throw new Error(`Unbekannte Codepage: ${String(codeTable)}`);
|
|
259
|
+
}
|
|
260
|
+
doc.globalCodeTable = codeTable;
|
|
261
|
+
if (codeTable !== null) {
|
|
262
|
+
anhaengen(doc, [...C_CODE_TABLE, CODEPAGE_ID[codeTable]]);
|
|
263
|
+
doc.styles.codeTable = codeTable;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* `ESC M n`: Schrift waehlen. Die Schrift bestimmt auch, wie viele Zeichen in
|
|
268
|
+
* eine Zeile passen (32/42 bei 58 mm, 48/64 bei 80 mm).
|
|
269
|
+
*/
|
|
270
|
+
function escPosSetGlobalFont(doc, font, options = {}) {
|
|
271
|
+
doc.globalFont = font;
|
|
272
|
+
if (font === null)
|
|
273
|
+
return;
|
|
274
|
+
const grenze = options.maxCharsPerLine ?? escPosMaxCharsPerLine(doc.paperSize, font);
|
|
275
|
+
if (!istGanzzahl(grenze) || grenze < 1) {
|
|
276
|
+
throw new Error('maxCharsPerLine muss eine Ganzzahl >= 1 sein');
|
|
277
|
+
}
|
|
278
|
+
doc.maxCharsPerLine = grenze;
|
|
279
|
+
anhaengen(doc, font === 'fontB' ? C_FONT_B : C_FONT_A);
|
|
280
|
+
doc.styles.fontType = font;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Sendet die Stilbefehle, die sich gegenueber dem zuletzt gesendeten Stand
|
|
284
|
+
* geaendert haben. Fehlende Felder in [styles] gelten als Vorgabe: wer fett
|
|
285
|
+
* weglaesst, schaltet fett also ab.
|
|
286
|
+
*/
|
|
287
|
+
function escPosSetStyles(doc, styles = {}) {
|
|
288
|
+
const neu = vollstaendigeStile(styles);
|
|
289
|
+
const alt = doc.styles;
|
|
290
|
+
if (neu.align !== alt.align) {
|
|
291
|
+
anhaengen(doc, neu.align === 'left' ? C_ALIGN_LEFT : neu.align === 'center' ? C_ALIGN_CENTER : C_ALIGN_RIGHT);
|
|
292
|
+
alt.align = neu.align;
|
|
293
|
+
}
|
|
294
|
+
if (neu.bold !== alt.bold) {
|
|
295
|
+
anhaengen(doc, neu.bold ? C_BOLD_ON : C_BOLD_OFF);
|
|
296
|
+
alt.bold = neu.bold;
|
|
297
|
+
}
|
|
298
|
+
if (neu.turn90 !== alt.turn90) {
|
|
299
|
+
anhaengen(doc, neu.turn90 ? C_TURN90_ON : C_TURN90_OFF);
|
|
300
|
+
alt.turn90 = neu.turn90;
|
|
301
|
+
}
|
|
302
|
+
if (neu.reverse !== alt.reverse) {
|
|
303
|
+
anhaengen(doc, neu.reverse ? C_REVERSE_ON : C_REVERSE_OFF);
|
|
304
|
+
alt.reverse = neu.reverse;
|
|
305
|
+
}
|
|
306
|
+
if (neu.underline !== alt.underline) {
|
|
307
|
+
anhaengen(doc, neu.underline ? C_UNDERLINE_1DOT : C_UNDERLINE_OFF);
|
|
308
|
+
alt.underline = neu.underline;
|
|
309
|
+
}
|
|
310
|
+
if (neu.fontType !== null && neu.fontType !== alt.fontType) {
|
|
311
|
+
anhaengen(doc, neu.fontType === 'fontB' ? C_FONT_B : C_FONT_A);
|
|
312
|
+
alt.fontType = neu.fontType;
|
|
313
|
+
}
|
|
314
|
+
else if (doc.globalFont !== null && doc.globalFont !== alt.fontType) {
|
|
315
|
+
anhaengen(doc, doc.globalFont === 'fontB' ? C_FONT_B : C_FONT_A);
|
|
316
|
+
alt.fontType = doc.globalFont;
|
|
317
|
+
}
|
|
318
|
+
if (neu.height !== alt.height || neu.width !== alt.width) {
|
|
319
|
+
anhaengen(doc, [...C_SIZE, groessenByte(neu.height, neu.width)]);
|
|
320
|
+
alt.height = neu.height;
|
|
321
|
+
alt.width = neu.width;
|
|
322
|
+
}
|
|
323
|
+
// Kanji-Modus abschalten: sonst deutet der Drucker Byte-Paare als
|
|
324
|
+
// Doppelbyte-Zeichen. Wird bewusst jedes Mal gesendet.
|
|
325
|
+
anhaengen(doc, C_KANJI_OFF);
|
|
326
|
+
const codepage = neu.codeTable ?? doc.globalCodeTable;
|
|
327
|
+
if (codepage !== null) {
|
|
328
|
+
anhaengen(doc, [...C_CODE_TABLE, CODEPAGE_ID[codepage]]);
|
|
329
|
+
alt.codeTable = codepage;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Interner Textdruck: absolute Position setzen (`ESC $`), Stil senden, Bytes
|
|
334
|
+
* ausgeben. [colInd]/[colWidth] beschreiben die Spalte im Zwoelftel-Raster.
|
|
335
|
+
*/
|
|
336
|
+
/**
|
|
337
|
+
* Wortweiser Umbruch von (kodierten) Text-Bytes auf hoechstens `max` Zeichen
|
|
338
|
+
* je Zeile: geschnitten wird am letzten Leerzeichen innerhalb der Grenze
|
|
339
|
+
* (das Leerzeichen selbst faellt weg); gibt es keines, hart bei `max` --
|
|
340
|
+
* sonst kaeme die Zeile nie voran. Ein Bondrucker bricht sonst hart mitten
|
|
341
|
+
* im Wort ("Kleinunter|nehmer", "0,7|9"); das soll nie aufs Papier.
|
|
342
|
+
*/
|
|
343
|
+
function escPosWortzeilen(textBytes, max) {
|
|
344
|
+
const grenze = Math.max(1, Math.floor(max));
|
|
345
|
+
const out = [];
|
|
346
|
+
let rest = textBytes;
|
|
347
|
+
while (rest.length > grenze) {
|
|
348
|
+
let schnitt = grenze;
|
|
349
|
+
if (rest[grenze] === 0x20) {
|
|
350
|
+
schnitt = grenze;
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
let i = grenze - 1;
|
|
354
|
+
while (i > 0 && rest[i] !== 0x20)
|
|
355
|
+
i -= 1;
|
|
356
|
+
if (i > 0)
|
|
357
|
+
schnitt = i;
|
|
358
|
+
else {
|
|
359
|
+
let h = grenze - 1;
|
|
360
|
+
while (h > 0 && rest[h] !== 0x2d)
|
|
361
|
+
h -= 1; // Bindestrich
|
|
362
|
+
if (h > 0)
|
|
363
|
+
schnitt = h + 1;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
let ende = schnitt;
|
|
367
|
+
while (ende > 0 && rest[ende - 1] === 0x20)
|
|
368
|
+
ende -= 1; // Leerzeichen am Zeilenende weg
|
|
369
|
+
out.push(ohneNbsp(rest.slice(0, ende)));
|
|
370
|
+
let weiter = schnitt;
|
|
371
|
+
while (weiter < rest.length && rest[weiter] === 0x20)
|
|
372
|
+
weiter += 1;
|
|
373
|
+
rest = rest.slice(weiter);
|
|
374
|
+
}
|
|
375
|
+
out.push(ohneNbsp(rest));
|
|
376
|
+
return out;
|
|
377
|
+
}
|
|
378
|
+
/** Geschuetztes Leerzeichen (0xA0, Latin-1) -> normales Leerzeichen fuer die Ausgabe. */
|
|
379
|
+
function ohneNbsp(b) {
|
|
380
|
+
if (!b.some((x) => x === 0xa0))
|
|
381
|
+
return b;
|
|
382
|
+
return b.map((x) => (x === 0xa0 ? 0x20 : x));
|
|
383
|
+
}
|
|
384
|
+
/** Zeilen wieder zu einem Text (mit Leerzeichen) -- fuer den Rest einer Spalte. */
|
|
385
|
+
function verketten(teile) {
|
|
386
|
+
const laenge = teile.reduce((n, t) => n + t.length, 0) + Math.max(0, teile.length - 1);
|
|
387
|
+
const out = new Uint8Array(laenge);
|
|
388
|
+
let pos = 0;
|
|
389
|
+
teile.forEach((t, i) => {
|
|
390
|
+
if (i > 0) {
|
|
391
|
+
out[pos] = 0x20;
|
|
392
|
+
pos += 1;
|
|
393
|
+
}
|
|
394
|
+
out.set(t, pos);
|
|
395
|
+
pos += t.length;
|
|
396
|
+
});
|
|
397
|
+
return out;
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Dieselbe Regel fuer Zeichenketten -- fuer Bildschirm-Vorschauen, die das
|
|
401
|
+
* Papier nachstellen, und fuer das Zeichenraster. Zusaetzlich:
|
|
402
|
+
* - geschuetztes Leerzeichen (U+00A0) ist kein Umbruchpunkt ("je 0,79" bleibt
|
|
403
|
+
* zusammen) und wird als normales Leerzeichen ausgegeben;
|
|
404
|
+
* - ein ueberlanges Wort bricht nach einem Bindestrich, wenn es einen hat
|
|
405
|
+
* ("Bio-" / "Dinkelvollkornsemmel"), sonst hart.
|
|
406
|
+
*/
|
|
407
|
+
function wortzeilenText(text, max) {
|
|
408
|
+
const grenze = Math.max(1, Math.floor(max));
|
|
409
|
+
const out = [];
|
|
410
|
+
let rest = text;
|
|
411
|
+
while (rest.length > grenze) {
|
|
412
|
+
let schnitt = grenze;
|
|
413
|
+
if (rest[grenze] !== ' ') {
|
|
414
|
+
let i = grenze - 1;
|
|
415
|
+
while (i > 0 && rest[i] !== ' ')
|
|
416
|
+
i -= 1;
|
|
417
|
+
if (i > 0)
|
|
418
|
+
schnitt = i;
|
|
419
|
+
else {
|
|
420
|
+
// kein Leerzeichen: nach dem letzten Bindestrich innerhalb der Grenze brechen
|
|
421
|
+
let h = grenze - 1;
|
|
422
|
+
while (h > 0 && rest[h] !== '-')
|
|
423
|
+
h -= 1;
|
|
424
|
+
if (h > 0)
|
|
425
|
+
schnitt = h + 1;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
out.push(rest.slice(0, schnitt).replace(/ +$/, '').replace(/\u00a0/g, ' '));
|
|
429
|
+
let weiter = schnitt;
|
|
430
|
+
while (weiter < rest.length && rest[weiter] === ' ')
|
|
431
|
+
weiter += 1;
|
|
432
|
+
rest = rest.slice(weiter);
|
|
433
|
+
}
|
|
434
|
+
out.push(rest.replace(/\u00a0/g, ' '));
|
|
435
|
+
return out;
|
|
436
|
+
}
|
|
437
|
+
function textIntern(doc, textBytes, optionen = {}) {
|
|
438
|
+
const stile = vollstaendigeStile(optionen.styles);
|
|
439
|
+
const colInd = optionen.colInd ?? 0;
|
|
440
|
+
const colWidth = optionen.colWidth ?? 12;
|
|
441
|
+
const breiteJeZeichen = zeichenBreite(doc, stile);
|
|
442
|
+
let von = spaltenPosition(doc, colInd);
|
|
443
|
+
if (colWidth !== 12) {
|
|
444
|
+
const bis = spaltenPosition(doc, colInd + colWidth) - doc.spaceBetweenRows;
|
|
445
|
+
const textLaenge = textBytes.length * breiteJeZeichen;
|
|
446
|
+
if (stile.align === 'right') {
|
|
447
|
+
von = bis - textLaenge;
|
|
448
|
+
}
|
|
449
|
+
else if (stile.align === 'center') {
|
|
450
|
+
von = von + (bis - von) / 2 - textLaenge / 2;
|
|
451
|
+
}
|
|
452
|
+
if (von < 0)
|
|
453
|
+
von = 0;
|
|
454
|
+
}
|
|
455
|
+
const position = runden(von);
|
|
456
|
+
anhaengen(doc, [...C_POS, position & 0xff, (position >> 8) & 0xff]);
|
|
457
|
+
escPosSetStyles(doc, optionen.styles);
|
|
458
|
+
anhaengen(doc, textBytes);
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Druckt Text und schliesst die Zeile ab. Nach dem Text folgt immer genau ein
|
|
462
|
+
* Zeilenumbruch, `linesAfter` haengt weitere an.
|
|
463
|
+
*/
|
|
464
|
+
function escPosText(doc, text, options = {}) {
|
|
465
|
+
const zusaetzlich = options.linesAfter ?? 0;
|
|
466
|
+
if (!istGanzzahl(zusaetzlich) || zusaetzlich < 0) {
|
|
467
|
+
throw new Error('linesAfter muss eine Ganzzahl >= 0 sein');
|
|
468
|
+
}
|
|
469
|
+
// Laengere Texte wortweise auf die Zeilenbreite brechen -- der Drucker
|
|
470
|
+
// selbst wuerde hart mitten im Wort umbrechen.
|
|
471
|
+
const stile = vollstaendigeStile(options.styles);
|
|
472
|
+
const zeichenJeZeile = Math.max(1, Math.floor(zeichenProZeile(doc, stile) / (stile.width === 2 ? 2 : 1)));
|
|
473
|
+
const zeilen = escPosWortzeilen(encodeEscPosText(text, doc.globalCodeTable ?? 'CP1252'), zeichenJeZeile);
|
|
474
|
+
zeilen.forEach((z, i) => {
|
|
475
|
+
textIntern(doc, z, { styles: options.styles });
|
|
476
|
+
if (i < zeilen.length - 1)
|
|
477
|
+
escPosEmptyLines(doc, 1);
|
|
478
|
+
});
|
|
479
|
+
escPosEmptyLines(doc, zusaetzlich + 1);
|
|
480
|
+
}
|
|
481
|
+
/** [n] Zeilenumbrueche (0x0A) — nicht der Vorschubbefehl, sondern echte Umbrueche. */
|
|
482
|
+
function escPosEmptyLines(doc, n) {
|
|
483
|
+
if (!istGanzzahl(n) || n < 0) {
|
|
484
|
+
throw new Error('Zeilenzahl muss eine Ganzzahl >= 0 sein');
|
|
485
|
+
}
|
|
486
|
+
for (let i = 0; i < n; i++) {
|
|
487
|
+
doc.bytes.push(ZEILENUMBRUCH);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
/** `ESC d n`: Papier um [n] Zeilen vorschieben. */
|
|
491
|
+
function escPosFeed(doc, n) {
|
|
492
|
+
if (!istGanzzahl(n) || n < 0 || n > 255) {
|
|
493
|
+
throw new Error('Vorschub muss eine Ganzzahl zwischen 0 und 255 sein');
|
|
494
|
+
}
|
|
495
|
+
anhaengen(doc, [...C_FEED_N, n]);
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Papierschnitt: fuenf Leerzeilen (damit der Text ueber der Schneide steht)
|
|
499
|
+
* und danach `GS V 0` bzw. `GS V 1`.
|
|
500
|
+
*/
|
|
501
|
+
function escPosCut(doc, mode = 'full') {
|
|
502
|
+
escPosEmptyLines(doc, 5);
|
|
503
|
+
anhaengen(doc, mode === 'partial' ? C_CUT_PART : C_CUT_FULL);
|
|
504
|
+
}
|
|
505
|
+
/** Trennlinie ueber die volle Zeilenbreite (oder [len] Zeichen). */
|
|
506
|
+
function escPosHr(doc, options = {}) {
|
|
507
|
+
const zeichen = options.ch ?? '-';
|
|
508
|
+
if (zeichen.length === 0) {
|
|
509
|
+
throw new Error('Fuellzeichen darf nicht leer sein');
|
|
510
|
+
}
|
|
511
|
+
const laenge = options.len ?? doc.maxCharsPerLine ?? escPosMaxCharsPerLine(doc.paperSize, doc.styles.fontType);
|
|
512
|
+
if (!istGanzzahl(laenge) || laenge < 0) {
|
|
513
|
+
throw new Error('Laenge der Trennlinie muss eine Ganzzahl >= 0 sein');
|
|
514
|
+
}
|
|
515
|
+
const textOptionen = {};
|
|
516
|
+
if (options.linesAfter !== undefined)
|
|
517
|
+
textOptionen.linesAfter = options.linesAfter;
|
|
518
|
+
escPosText(doc, zeichen.charAt(0).repeat(laenge), textOptionen);
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Druckt eine Zeile aus bis zu zwoelf Spalten. Die Breiten (Zwoelftel) muessen
|
|
522
|
+
* zusammen 12 ergeben. Passt der Inhalt einer Spalte nicht, laeuft der Rest in
|
|
523
|
+
* eine Folgezeile.
|
|
524
|
+
*/
|
|
525
|
+
function escPosRow(doc, columns) {
|
|
526
|
+
let summe = 0;
|
|
527
|
+
for (const spalte of columns) {
|
|
528
|
+
if (!istGanzzahl(spalte.width) || spalte.width < 1 || spalte.width > 12) {
|
|
529
|
+
throw new Error('Spaltenbreite muss eine Ganzzahl im Bereich 1..12 sein');
|
|
530
|
+
}
|
|
531
|
+
if (spalte.text !== undefined &&
|
|
532
|
+
spalte.text.length > 0 &&
|
|
533
|
+
spalte.textEncoded !== undefined &&
|
|
534
|
+
spalte.textEncoded.length > 0) {
|
|
535
|
+
throw new Error('Nur text oder textEncoded angeben, nicht beides');
|
|
536
|
+
}
|
|
537
|
+
summe += spalte.width;
|
|
538
|
+
}
|
|
539
|
+
if (summe !== 12) {
|
|
540
|
+
throw new Error(`Die Spaltenbreiten muessen zusammen 12 ergeben (waren ${summe})`);
|
|
541
|
+
}
|
|
542
|
+
// Schleife statt Rekursion: bei sehr langem Spalteninhalt (und erst recht,
|
|
543
|
+
// wenn die Untergrenze von einem Zeichen je Zeile greift) waeren es sonst
|
|
544
|
+
// ebenso viele Aufrufrahmen wie Folgezeilen.
|
|
545
|
+
let aktuelle = columns;
|
|
546
|
+
for (;;) {
|
|
547
|
+
let hatFolgezeile = false;
|
|
548
|
+
const folgezeile = [];
|
|
549
|
+
let spaltenIndex = 0;
|
|
550
|
+
for (const spalte of aktuelle) {
|
|
551
|
+
const stile = vollstaendigeStile(spalte.styles);
|
|
552
|
+
const breiteJeZeichen = zeichenBreite(doc, stile);
|
|
553
|
+
const von = spaltenPosition(doc, spaltenIndex);
|
|
554
|
+
const bis = spaltenPosition(doc, spaltenIndex + spalte.width) - doc.spaceBetweenRows;
|
|
555
|
+
// Mindestens ein Zeichen je Zeile, sonst kaeme die Folgezeile nie voran.
|
|
556
|
+
const maxZeichen = Math.max(1, Math.floor((bis - von) / breiteJeZeichen));
|
|
557
|
+
let zuDrucken = spalte.textEncoded ?? encodeEscPosText(spalte.text ?? '', doc.globalCodeTable ?? 'CP1252');
|
|
558
|
+
const folge = { width: spalte.width };
|
|
559
|
+
if (spalte.styles !== undefined)
|
|
560
|
+
folge.styles = spalte.styles;
|
|
561
|
+
if (zuDrucken.length > maxZeichen) {
|
|
562
|
+
// Wortweise: erste Zeile bis zum letzten Leerzeichen innerhalb der
|
|
563
|
+
// Spalte, der Rest (ohne fuehrende Leerzeichen) in die Folgezeile.
|
|
564
|
+
const [erste, ...weitere] = escPosWortzeilen(zuDrucken, maxZeichen);
|
|
565
|
+
const rest = weitere.length ? verketten(weitere) : new Uint8Array(0);
|
|
566
|
+
folge.textEncoded = rest;
|
|
567
|
+
zuDrucken = erste;
|
|
568
|
+
hatFolgezeile = rest.length > 0;
|
|
569
|
+
}
|
|
570
|
+
else {
|
|
571
|
+
folge.text = '';
|
|
572
|
+
}
|
|
573
|
+
folgezeile.push(folge);
|
|
574
|
+
const textOptionen = {
|
|
575
|
+
colInd: spaltenIndex,
|
|
576
|
+
colWidth: spalte.width,
|
|
577
|
+
};
|
|
578
|
+
if (spalte.styles !== undefined)
|
|
579
|
+
textOptionen.styles = spalte.styles;
|
|
580
|
+
textIntern(doc, zuDrucken, textOptionen);
|
|
581
|
+
spaltenIndex += spalte.width;
|
|
582
|
+
}
|
|
583
|
+
escPosEmptyLines(doc, 1);
|
|
584
|
+
if (!hatFolgezeile)
|
|
585
|
+
return;
|
|
586
|
+
aktuelle = folgezeile;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Bytes des nativen QR-Befehls (`GS ( k`, Funktionen 167/169/180/182/181) —
|
|
591
|
+
* ohne Ausrichtung, ohne Zeilenumbruch. Der Drucker zeichnet den Code selbst;
|
|
592
|
+
* es wird kein Bild uebertragen.
|
|
593
|
+
*
|
|
594
|
+
* Bei Kasseneck-Belegen steht hier der maschinenlesbare RKSV-Code.
|
|
595
|
+
*/
|
|
596
|
+
function qrCodeBytes(text, options = {}) {
|
|
597
|
+
const size = options.size ?? 4;
|
|
598
|
+
if (!istGanzzahl(size) || size < 1 || size > 8) {
|
|
599
|
+
throw new Error('QR-Modulgroesse muss eine Ganzzahl im Bereich 1..8 sein');
|
|
600
|
+
}
|
|
601
|
+
const correction = options.correction ?? 'L';
|
|
602
|
+
const stufe = QR_KORREKTUR[correction];
|
|
603
|
+
if (stufe === undefined) {
|
|
604
|
+
throw new Error(`Unbekannte QR-Fehlerkorrektur: ${String(correction)}`);
|
|
605
|
+
}
|
|
606
|
+
const daten = latin1(text);
|
|
607
|
+
const laenge = daten.length + 3;
|
|
608
|
+
if (laenge > 0xffff) {
|
|
609
|
+
throw new Error('QR-Inhalt ist zu lang');
|
|
610
|
+
}
|
|
611
|
+
const bytes = [];
|
|
612
|
+
// Funktion 167: Modulgroesse
|
|
613
|
+
bytes.push(...C_QR_HEADER, 0x03, 0x00, 0x31, 0x43, size);
|
|
614
|
+
// Funktion 169: Fehlerkorrektur
|
|
615
|
+
bytes.push(...C_QR_HEADER, 0x03, 0x00, 0x31, 0x45, stufe);
|
|
616
|
+
// Funktion 180: Daten in den Symbolspeicher; pL/pH = Laenge + 3
|
|
617
|
+
bytes.push(...C_QR_HEADER, laenge & 0xff, (laenge >> 8) & 0xff, 0x31, 0x50, 0x30);
|
|
618
|
+
for (let i = 0; i < daten.length; i++) {
|
|
619
|
+
bytes.push(daten[i]);
|
|
620
|
+
}
|
|
621
|
+
// Funktion 182: Groesse der Symboldaten abfragen
|
|
622
|
+
bytes.push(...C_QR_HEADER, 0x03, 0x00, 0x31, 0x52, 0x30);
|
|
623
|
+
// Funktion 181: Symbol drucken
|
|
624
|
+
bytes.push(...C_QR_HEADER, 0x03, 0x00, 0x31, 0x51, 0x30);
|
|
625
|
+
return Uint8Array.from(bytes);
|
|
626
|
+
}
|
|
627
|
+
/** Setzt die Ausrichtung und haengt den nativen QR-Befehl an. */
|
|
628
|
+
function escPosQrCode(doc, text, options = {}) {
|
|
629
|
+
escPosSetStyles(doc, { align: options.align ?? 'center' });
|
|
630
|
+
const qrOptionen = {};
|
|
631
|
+
if (options.size !== undefined)
|
|
632
|
+
qrOptionen.size = options.size;
|
|
633
|
+
if (options.correction !== undefined)
|
|
634
|
+
qrOptionen.correction = options.correction;
|
|
635
|
+
anhaengen(doc, qrCodeBytes(text, qrOptionen));
|
|
636
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { type PosPaperSize, type PosAlign, type PosFont, type PosCutMode, type PosCodeTable, type PosTextSize, type QrSize, type QrCorrection, type PosStyles, type PosColumn, type EscPosOptions, type EscPosTextOptions, type EscPosHrOptions, type EscPosQrOptions, type EscPosDocument, createEscPosDocument, escPosBytes, escPosReset, escPosSetGlobalCodeTable, escPosSetGlobalFont, escPosSetStyles, escPosText, escPosEmptyLines, escPosFeed, escPosCut, escPosHr, escPosRow, escPosQrCode, encodeEscPosText, qrCodeBytes, escPosMaxCharsPerLine, escPosWortzeilen, wortzeilenText, } from './escpos.js';
|
|
2
|
+
export { escPosPrintableText } from './printable.js';
|
|
3
|
+
export { type UsbEndpointLike, type UsbAlternateLike, type UsbInterfaceLike, type UsbConfigurationLike, type UsbTransferOutResultLike, type UsbWriterLike, type UsbIdentityLike, type UsbDeviceLike, type UsbPrinterEndpoint, type UsbPrinterConnection, USB_VENDOR_EPSON, USB_CLASS_PRINTER, usbDeviceKey, usbFindPrinterEndpoint, usbWriteAll, usbConnectPrinter, usbPrint, usbDisconnect, } from './webusb.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.usbDisconnect = exports.usbPrint = exports.usbConnectPrinter = exports.usbWriteAll = exports.usbFindPrinterEndpoint = exports.usbDeviceKey = exports.USB_CLASS_PRINTER = exports.USB_VENDOR_EPSON = exports.escPosPrintableText = exports.wortzeilenText = exports.escPosWortzeilen = exports.escPosMaxCharsPerLine = exports.qrCodeBytes = exports.encodeEscPosText = exports.escPosQrCode = exports.escPosRow = exports.escPosHr = exports.escPosCut = exports.escPosFeed = exports.escPosEmptyLines = exports.escPosText = exports.escPosSetStyles = exports.escPosSetGlobalFont = exports.escPosSetGlobalCodeTable = exports.escPosReset = exports.escPosBytes = exports.createEscPosDocument = void 0;
|
|
4
|
+
var escpos_js_1 = require("./escpos.js");
|
|
5
|
+
Object.defineProperty(exports, "createEscPosDocument", { enumerable: true, get: function () { return escpos_js_1.createEscPosDocument; } });
|
|
6
|
+
Object.defineProperty(exports, "escPosBytes", { enumerable: true, get: function () { return escpos_js_1.escPosBytes; } });
|
|
7
|
+
Object.defineProperty(exports, "escPosReset", { enumerable: true, get: function () { return escpos_js_1.escPosReset; } });
|
|
8
|
+
Object.defineProperty(exports, "escPosSetGlobalCodeTable", { enumerable: true, get: function () { return escpos_js_1.escPosSetGlobalCodeTable; } });
|
|
9
|
+
Object.defineProperty(exports, "escPosSetGlobalFont", { enumerable: true, get: function () { return escpos_js_1.escPosSetGlobalFont; } });
|
|
10
|
+
Object.defineProperty(exports, "escPosSetStyles", { enumerable: true, get: function () { return escpos_js_1.escPosSetStyles; } });
|
|
11
|
+
Object.defineProperty(exports, "escPosText", { enumerable: true, get: function () { return escpos_js_1.escPosText; } });
|
|
12
|
+
Object.defineProperty(exports, "escPosEmptyLines", { enumerable: true, get: function () { return escpos_js_1.escPosEmptyLines; } });
|
|
13
|
+
Object.defineProperty(exports, "escPosFeed", { enumerable: true, get: function () { return escpos_js_1.escPosFeed; } });
|
|
14
|
+
Object.defineProperty(exports, "escPosCut", { enumerable: true, get: function () { return escpos_js_1.escPosCut; } });
|
|
15
|
+
Object.defineProperty(exports, "escPosHr", { enumerable: true, get: function () { return escpos_js_1.escPosHr; } });
|
|
16
|
+
Object.defineProperty(exports, "escPosRow", { enumerable: true, get: function () { return escpos_js_1.escPosRow; } });
|
|
17
|
+
Object.defineProperty(exports, "escPosQrCode", { enumerable: true, get: function () { return escpos_js_1.escPosQrCode; } });
|
|
18
|
+
Object.defineProperty(exports, "encodeEscPosText", { enumerable: true, get: function () { return escpos_js_1.encodeEscPosText; } });
|
|
19
|
+
Object.defineProperty(exports, "qrCodeBytes", { enumerable: true, get: function () { return escpos_js_1.qrCodeBytes; } });
|
|
20
|
+
Object.defineProperty(exports, "escPosMaxCharsPerLine", { enumerable: true, get: function () { return escpos_js_1.escPosMaxCharsPerLine; } });
|
|
21
|
+
Object.defineProperty(exports, "escPosWortzeilen", { enumerable: true, get: function () { return escpos_js_1.escPosWortzeilen; } });
|
|
22
|
+
Object.defineProperty(exports, "wortzeilenText", { enumerable: true, get: function () { return escpos_js_1.wortzeilenText; } });
|
|
23
|
+
var printable_js_1 = require("./printable.js");
|
|
24
|
+
Object.defineProperty(exports, "escPosPrintableText", { enumerable: true, get: function () { return printable_js_1.escPosPrintableText; } });
|
|
25
|
+
var webusb_js_1 = require("./webusb.js");
|
|
26
|
+
Object.defineProperty(exports, "USB_VENDOR_EPSON", { enumerable: true, get: function () { return webusb_js_1.USB_VENDOR_EPSON; } });
|
|
27
|
+
Object.defineProperty(exports, "USB_CLASS_PRINTER", { enumerable: true, get: function () { return webusb_js_1.USB_CLASS_PRINTER; } });
|
|
28
|
+
Object.defineProperty(exports, "usbDeviceKey", { enumerable: true, get: function () { return webusb_js_1.usbDeviceKey; } });
|
|
29
|
+
Object.defineProperty(exports, "usbFindPrinterEndpoint", { enumerable: true, get: function () { return webusb_js_1.usbFindPrinterEndpoint; } });
|
|
30
|
+
Object.defineProperty(exports, "usbWriteAll", { enumerable: true, get: function () { return webusb_js_1.usbWriteAll; } });
|
|
31
|
+
Object.defineProperty(exports, "usbConnectPrinter", { enumerable: true, get: function () { return webusb_js_1.usbConnectPrinter; } });
|
|
32
|
+
Object.defineProperty(exports, "usbPrint", { enumerable: true, get: function () { return webusb_js_1.usbPrint; } });
|
|
33
|
+
Object.defineProperty(exports, "usbDisconnect", { enumerable: true, get: function () { return webusb_js_1.usbDisconnect; } });
|