@kreiseck/kasseneck-api 0.13.2 → 0.14.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.
Files changed (146) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/README.md +31 -5
  3. package/dist/cjs/client/receipts.d.ts +7 -0
  4. package/dist/cjs/client/receipts.js +1 -0
  5. package/dist/cjs/kasse/drucker.d.ts +5 -0
  6. package/dist/cjs/kasse/drucker.js +9 -0
  7. package/dist/cjs/kasse/settings.js +5 -2
  8. package/dist/cjs/printing/escpos.d.ts +38 -4
  9. package/dist/cjs/printing/escpos.js +87 -15
  10. package/dist/cjs/printing/index.d.ts +2 -2
  11. package/dist/cjs/printing/index.js +5 -1
  12. package/dist/cjs/printing/qr-groesse.d.ts +26 -21
  13. package/dist/cjs/printing/qr-groesse.js +22 -8
  14. package/dist/cjs/react/index.d.ts +53 -0
  15. package/dist/cjs/react/index.js +81 -0
  16. package/dist/cjs/receipt/bild.d.ts +14 -0
  17. package/dist/cjs/receipt/bild.js +65 -0
  18. package/dist/cjs/receipt/blatt.d.ts +107 -0
  19. package/dist/cjs/receipt/blatt.js +137 -0
  20. package/dist/cjs/receipt/epos.d.ts +19 -8
  21. package/dist/cjs/receipt/epos.js +39 -20
  22. package/dist/cjs/receipt/grid.d.ts +1 -1
  23. package/dist/cjs/receipt/grid.js +9 -1
  24. package/dist/cjs/receipt/index.d.ts +4 -2
  25. package/dist/cjs/receipt/index.js +17 -1
  26. package/dist/cjs/receipt/layout-escpos.d.ts +31 -3
  27. package/dist/cjs/receipt/layout-escpos.js +58 -18
  28. package/dist/esm/client/receipts.d.ts +7 -0
  29. package/dist/esm/client/receipts.js +1 -0
  30. package/dist/esm/kasse/drucker.d.ts +5 -0
  31. package/dist/esm/kasse/drucker.js +9 -0
  32. package/dist/esm/kasse/settings.js +5 -2
  33. package/dist/esm/printing/escpos.d.ts +38 -4
  34. package/dist/esm/printing/escpos.js +84 -15
  35. package/dist/esm/printing/index.d.ts +2 -2
  36. package/dist/esm/printing/index.js +2 -2
  37. package/dist/esm/printing/qr-groesse.d.ts +26 -21
  38. package/dist/esm/printing/qr-groesse.js +21 -8
  39. package/dist/esm/react/index.d.ts +53 -0
  40. package/dist/esm/react/index.js +80 -1
  41. package/dist/esm/receipt/bild.d.ts +14 -0
  42. package/dist/esm/receipt/bild.js +62 -0
  43. package/dist/esm/receipt/blatt.d.ts +107 -0
  44. package/dist/esm/receipt/blatt.js +128 -0
  45. package/dist/esm/receipt/epos.d.ts +19 -8
  46. package/dist/esm/receipt/epos.js +40 -22
  47. package/dist/esm/receipt/grid.d.ts +1 -1
  48. package/dist/esm/receipt/grid.js +9 -1
  49. package/dist/esm/receipt/index.d.ts +4 -2
  50. package/dist/esm/receipt/index.js +4 -2
  51. package/dist/esm/receipt/layout-escpos.d.ts +31 -3
  52. package/dist/esm/receipt/layout-escpos.js +58 -20
  53. package/fixtures/erwartet/karte-eigener.blatt32.json +159 -0
  54. package/fixtures/erwartet/karte-eigener.blatt48.json +159 -0
  55. package/fixtures/erwartet/karte-gptom-ios.blatt32.json +231 -0
  56. package/fixtures/erwartet/karte-gptom-ios.blatt48.json +231 -0
  57. package/fixtures/erwartet/karte-gptom.blatt32.json +231 -0
  58. package/fixtures/erwartet/karte-gptom.blatt48.json +231 -0
  59. package/fixtures/erwartet/karte-hobex-cloud.blatt32.json +201 -0
  60. package/fixtures/erwartet/karte-hobex-cloud.blatt48.json +201 -0
  61. package/fixtures/erwartet/karte-hobex-hps.blatt32.json +225 -0
  62. package/fixtures/erwartet/karte-hobex-hps.blatt48.json +225 -0
  63. package/fixtures/erwartet/karte-mypos.blatt32.json +255 -0
  64. package/fixtures/erwartet/karte-mypos.blatt48.json +243 -0
  65. package/fixtures/erwartet/karte-stripe-eps.blatt32.json +195 -0
  66. package/fixtures/erwartet/karte-stripe-eps.blatt48.json +195 -0
  67. package/fixtures/erwartet/karte-stripe.blatt32.json +213 -0
  68. package/fixtures/erwartet/karte-stripe.blatt48.json +213 -0
  69. package/fixtures/erwartet/karte-sumup.blatt32.json +219 -0
  70. package/fixtures/erwartet/karte-sumup.blatt48.json +207 -0
  71. package/fixtures/erwartet/langer-artikelname.blatt32.json +177 -0
  72. package/fixtures/erwartet/langer-artikelname.blatt48.json +171 -0
  73. package/fixtures/erwartet/logo-probe-hoch.raster32.txt +120 -0
  74. package/fixtures/erwartet/logo-probe.raster32.txt +54 -0
  75. package/fixtures/erwartet/null-ausfall.blatt32.json +207 -0
  76. package/fixtures/erwartet/null-ausfall.blatt48.json +189 -0
  77. package/fixtures/erwartet/null-ausfall.grid32.txt +2 -0
  78. package/fixtures/erwartet/null-ausfall.grid48.txt +2 -0
  79. package/fixtures/erwartet/null-jahr.blatt32.json +213 -0
  80. package/fixtures/erwartet/null-jahr.blatt48.json +189 -0
  81. package/fixtures/erwartet/null-jahr.grid32.txt +2 -0
  82. package/fixtures/erwartet/null-jahr.grid48.txt +2 -0
  83. package/fixtures/erwartet/null-monat.blatt32.json +207 -0
  84. package/fixtures/erwartet/null-monat.blatt48.json +189 -0
  85. package/fixtures/erwartet/null-monat.grid32.txt +2 -0
  86. package/fixtures/erwartet/null-monat.grid48.txt +2 -0
  87. package/fixtures/erwartet/null-pruef.blatt32.json +207 -0
  88. package/fixtures/erwartet/null-pruef.blatt48.json +189 -0
  89. package/fixtures/erwartet/null-pruef.grid32.txt +2 -0
  90. package/fixtures/erwartet/null-pruef.grid48.txt +2 -0
  91. package/fixtures/erwartet/null-schluss.blatt32.json +207 -0
  92. package/fixtures/erwartet/null-schluss.blatt48.json +189 -0
  93. package/fixtures/erwartet/null-schluss.grid32.txt +2 -0
  94. package/fixtures/erwartet/null-schluss.grid48.txt +2 -0
  95. package/fixtures/erwartet/null-start.blatt32.json +207 -0
  96. package/fixtures/erwartet/null-start.blatt48.json +189 -0
  97. package/fixtures/erwartet/null-start.grid32.txt +2 -0
  98. package/fixtures/erwartet/null-start.grid48.txt +2 -0
  99. package/fixtures/erwartet/rabatt-chef-trinkgeld.blatt32.json +213 -0
  100. package/fixtures/erwartet/rabatt-chef-trinkgeld.blatt48.json +207 -0
  101. package/fixtures/erwartet/rabatt-einfach.blatt32.json +183 -0
  102. package/fixtures/erwartet/rabatt-einfach.blatt48.json +177 -0
  103. package/fixtures/erwartet/rabatt-trinkgeld.blatt32.json +213 -0
  104. package/fixtures/erwartet/rabatt-trinkgeld.blatt48.json +207 -0
  105. package/fixtures/erwartet/rabatt-wertgutschein.blatt32.json +219 -0
  106. package/fixtures/erwartet/rabatt-wertgutschein.blatt48.json +213 -0
  107. package/fixtures/erwartet/rabattzeilen.blatt32.json +201 -0
  108. package/fixtures/erwartet/rabattzeilen.blatt48.json +195 -0
  109. package/fixtures/erwartet/signaturausfall-verkauf.blatt32.json +195 -0
  110. package/fixtures/erwartet/signaturausfall-verkauf.blatt48.json +183 -0
  111. package/fixtures/erwartet/storno-rabatt.blatt32.json +249 -0
  112. package/fixtures/erwartet/storno-rabatt.blatt48.json +237 -0
  113. package/fixtures/erwartet/storno-rabatt.grid32.txt +2 -0
  114. package/fixtures/erwartet/storno-rabatt.grid48.txt +2 -0
  115. package/fixtures/erwartet/storno-teil.blatt32.json +207 -0
  116. package/fixtures/erwartet/storno-teil.blatt48.json +201 -0
  117. package/fixtures/erwartet/storno-teil.grid32.txt +2 -0
  118. package/fixtures/erwartet/storno-teil.grid48.txt +2 -0
  119. package/fixtures/erwartet/storno-voll.blatt32.json +219 -0
  120. package/fixtures/erwartet/storno-voll.blatt48.json +213 -0
  121. package/fixtures/erwartet/storno-voll.grid32.txt +2 -0
  122. package/fixtures/erwartet/storno-voll.grid48.txt +2 -0
  123. package/fixtures/erwartet/testkasse-verkauf.blatt32.json +225 -0
  124. package/fixtures/erwartet/testkasse-verkauf.blatt48.json +219 -0
  125. package/fixtures/erwartet/testkasse-verkauf.grid32.txt +5 -1
  126. package/fixtures/erwartet/testkasse-verkauf.grid48.txt +5 -1
  127. package/fixtures/erwartet/testsignatur-verkauf.blatt32.json +237 -0
  128. package/fixtures/erwartet/testsignatur-verkauf.blatt48.json +219 -0
  129. package/fixtures/erwartet/testsignatur-verkauf.grid32.txt +5 -1
  130. package/fixtures/erwartet/testsignatur-verkauf.grid48.txt +5 -1
  131. package/fixtures/erwartet/training.blatt32.json +237 -0
  132. package/fixtures/erwartet/training.blatt48.json +219 -0
  133. package/fixtures/erwartet/training.grid32.txt +2 -0
  134. package/fixtures/erwartet/training.grid48.txt +2 -0
  135. package/fixtures/erwartet/verkauf-bar.blatt32.json +177 -0
  136. package/fixtures/erwartet/verkauf-bar.blatt48.json +171 -0
  137. package/fixtures/erwartet/verkauf-karte.blatt32.json +177 -0
  138. package/fixtures/erwartet/verkauf-karte.blatt48.json +171 -0
  139. package/fixtures/erwartet/verkauf-kleinunternehmer.blatt32.json +183 -0
  140. package/fixtures/erwartet/verkauf-kleinunternehmer.blatt48.json +177 -0
  141. package/fixtures/hobex-hps-codes.json +1 -1
  142. package/fixtures/kasse-settings-standard.json +1 -1
  143. package/fixtures/kasse-texte.json +1 -1
  144. package/fixtures/manifest.json +109 -43
  145. package/fixtures/oberflaeche.json +1 -1
  146. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,76 @@ Was vor 0.7.0 geschah, steht in der Commit-Historie (`git log`); ab hier wird
4
4
  es hier geführt. Ein Eintrag nennt die Änderung **und ihren Grund** —
5
5
  nur der Grund überlebt den nächsten Umbau.
6
6
 
7
+ ## 0.14.0
8
+
9
+ ### Das Beleg-Blatt: ein Beleg, der überall gleich aussieht
10
+
11
+ **Anlass:** Derselbe Beleg sah in der App, am Bon, in der Web-Kasse, im Panel
12
+ und im PDF verschieden aus. Das Raster war als einzige Wahrheit gedacht, aber
13
+ jeder Zeichner setzte Rahmen, Logo und QR selbst: das Panel stellte das Logo
14
+ über den Testkassen-Rahmen, das PDF legte es darauf, die App zeigte keins, der
15
+ Bon druckte Warnungen invers und doppelt hoch.
16
+
17
+ - `renderReceiptGrid` gibt Aufdrucke als drei Rasterzeilen aus (`====`, Text,
18
+ `====`). ESC/POS und ePOS drucken sie als normale fette Zeilen — keine doppelte
19
+ Höhe, kein Invertieren mehr. `grid32`/`grid48` der Belege mit Aufdruck ändern
20
+ sich, das Zeilenmodell nicht.
21
+ - Bekannter Unterschied, bleibt so: ESC/POS druckt `EUR` statt `€` (die
22
+ Ein-Byte-Codepage des Bondruckers kennt das Zeichen nicht). Bildschirm, PDF
23
+ und ePOS zeigen `€`; die Zeilen sind dadurch am Bon an diesen Stellen anders
24
+ gefüllt, das Raster bleibt gleich breit.
25
+ - Neu `belegBlatt(layout, { zeichen, logo, marke, qrGroesse })`: Reihenfolge
26
+ (Aufdrucke oben, Leerzeile, Logo, Leerzeile, Beleg, Marke), Logo-Maß je Stufe
27
+ S/M/L/XL (nie hochgerechnet), QR-Anteil wie am Drucker.
28
+ - Ein QR-Inhalt, der in keine QR-Version passt (Korrektur M, mehr als 2331
29
+ Byte), bekommt im Blatt den Anteil 0, statt dass `belegBlatt` wirft. ESC/POS
30
+ und ePOS lassen den QR dann weg und melden es über `qrFehler`; der Beleg steht
31
+ ohne QR. Die Bildschirm-Ansicht ruft `renderQr` weiter mit der Nutzlast, damit
32
+ die Oberfläche den fehlenden QR anzeigen kann (Papierbeleg-Hinweis). **Grund:** Ein Wurf riss jeden Zeichner mit — die Bon-Ansicht der
33
+ Web-Kasse fiel ganz aus, Bon und PDF ebenso. Neu `qrPasstInVersion(nutzlast)`
34
+ (`./printing`); `qrModulAnzahl` wirft weiter.
35
+ - Neu `logoRaster` (RGBA → einfarbiges Rasterbild), `escPosRasterBild`,
36
+ `eposBildXml`; `escPosLayoutBytes` und `eposPrintXml` nehmen `logo` und `marke`.
37
+ - Neu `BelegBlattView` / `BelegBlattZeilen` (`./react`); `ReceiptLayoutView` ist
38
+ `@deprecated`. `BelegBlattView` zeigt ein Logo ueber 4096x4096px (oder 0)
39
+ ebenso wenig wie ein nicht geladenes -- neu `LOGO_PIXEL_MAX`,
40
+ `logoPixelZulaessig` (`./receipt`). **Grund:** Bildschirm und Bon zeigen
41
+ dasselbe Logo; das Druck-Kit lehnt ein zu grosses Logo beim Rastern fuer
42
+ den Bon schon ab (dieselbe Grenze), der Bildschirm bisher nicht -- ein
43
+ 5000x1200px-Logo erschien am Bildschirm und im PDF, aber nie auf dem
44
+ gedruckten Beleg.
45
+ - Neu `ReceiptWithCompany.logoStufe` (aus `logo_skala` der Beleg-Antwort,
46
+ Vorgabe `M`): Panel und App kannten die Logo-Stufe des Betriebs bisher nicht.
47
+ - `createPrintJob` nimmt `logo` und `marke`: der Netzwerk-Drucker (Connect)
48
+ druckt dasselbe Blatt wie USB, Bluetooth und ePOS direkt. Neu
49
+ `rasterZeilenBase64` (gemeinsam für ePOS-`<image>` und den Druckjob).
50
+ - Goldens `erwartet/<name>.blatt32.json`/`.blatt48.json`,
51
+ `erwartet/logo-probe.raster32.txt` (mit Teiltransparenz) und
52
+ `erwartet/logo-probe-hoch.raster32.txt` (höhenbegrenzt) für den Dart-Zwilling.
53
+ - `escPosRasterBild` wirft bei einer Bildhöhe über 65535 Punkten (`GS v 0` trägt
54
+ die Höhe in zwei Bytes).
55
+
56
+ ### Achtung: Brüche
57
+
58
+ - **Aufdrucke im Raster.** `renderReceiptGrid` gibt jeden Aufdruck als drei
59
+ Zeilen `kind:'banner'` aus (`====`, Text, `====`). *Umstellen:* eigene
60
+ Rahmen oder Sonderstile für Aufdrucke entfernen (sie stünden sonst doppelt)
61
+ und nicht annehmen, dass die erste `banner`-Zeile die einzige ist — der Text
62
+ steht in der mittleren.
63
+ - **`ReceiptWithCompany.logoStufe` ist Pflicht.** `getReceiptWithCompany` füllt
64
+ es selbst. *Umstellen:* von Hand gebaute Objekte (Tests, Vorschauen) brauchen
65
+ `logoStufe: 'M'`.
66
+ - **QR-Vorgabe `auto` deckelt bei 6 Punkten je Modul (vorher 4)** — in npm und
67
+ Dart dasselbe. Am ESC/POS-Bon wird der QR ohne ausdrückliche Wahl größer
68
+ (80 mm: rund 55 % statt 37 % der Breite). *Umstellen:* wer die alte Größe
69
+ will, stellt `qrGroesse: 'klein'`.
70
+ - **Nativer ESC/POS-QR mit Fehlerkorrektur M (vorher L)**, wie ePOS, Bildweg
71
+ und Blatt — der Kasten am Bildschirm ist damit genau der gedruckte QR.
72
+ Manche Nutzlasten brauchen eine Version mehr. *Umstellen:* den alten
73
+ Bytestrom liefert `qrCorrection: 'L'` (zusammen mit `qrGroesse: 'klein'`).
74
+ - **ePOS-Vorgabe `qrGroesse` ist `auto`** (vorher `mittel`). Derselbe Wert,
75
+ kein Byte anders; nur wer die Vorgabe ausliest oder dokumentiert, merkt es.
76
+
7
77
  ## 0.13.2
8
78
 
9
79
  ### Die Paketseite erklaert, wofuer das Paket da ist
package/README.md CHANGED
@@ -460,8 +460,9 @@ const mass = qrGroesseFuer({ nutzlast: beleg.qr, papierbreitePunkte: QR_DRUCK_PU
460
460
 
461
461
  Am Belegweg passiert das von selbst. `qrGroesse` ist ein **Deckel**, keine
462
462
  Vorgabe: gedruckt wird die größte Größe, die noch passt, höchstens aber der
463
- Deckel. `auto` (Vorgabe) deckelt beim Bestandswert 4 — ohne ausdrückliche Wahl
464
- ändert sich also kein Byte.
463
+ Deckel. `auto` (Vorgabe) deckelt bei 6 Punkten je Modul — wie im Dart-Zwilling
464
+ und am Epson-Weg; `klein` deckelt bei 4. Alle Druckwege setzen den QR mit
465
+ Fehlerkorrektur M.
465
466
 
466
467
  ```ts
467
468
  import { escPosLayoutErgebnis } from '@kreiseck/kasseneck-api/receipt';
@@ -474,8 +475,8 @@ const { bytes, qrFehler, qrAusweich } = escPosLayoutErgebnis(layout, {
474
475
  ```
475
476
 
476
477
  Der Epson-Weg (`eposPrintXml` / `eposDirectPrint`) rechnet genauso;
477
- `eposPrintXmlErgebnis` gibt dort `{ xml, qrFehler, qrAusweich }`. Sein
478
- Bestandswert ist 6, deshalb ist die Vorgabe dort der Deckel `mittel`.
478
+ `eposPrintXmlErgebnis` gibt dort `{ xml, qrFehler, qrAusweich }`. Die Vorgabe
479
+ ist auch dort `auto`.
479
480
 
480
481
  `qrFehler` heißt „Beleg ohne QR" — das gehört dem Kunden gesagt. `qrAusweich`
481
482
  heißt „gedruckt, aber der eingestellte Weg taugt für dieses Gerät nicht" — das
@@ -483,6 +484,30 @@ gehört dem Chef gesagt. Den Bildweg fährt das Paket nur mit einem `qrMatrix`,
483
484
  das die Nutzlast in ein fertiges Raster übersetzt: hier wird bewusst weder ein
484
485
  QR gerechnet noch ein Bild verarbeitet.
485
486
 
487
+ ## Das Beleg-Blatt: überall derselbe Beleg
488
+
489
+ Bildschirm, Bon, ePOS und PDF setzen dasselbe **Blatt**: Rasterzeilen, Firmenlogo,
490
+ QR und die Marke „erstellt mit Kasseneck", mit Größen als Anteil der Blattbreite
491
+ und in Zeilen (eine Zeile = zwei Zeichenbreiten).
492
+
493
+ ```tsx
494
+ import { BelegBlattView } from '@kreiseck/kasseneck-api/react';
495
+
496
+ <BelegBlattView layout={layout} logo={{ url: company.logoUrl, stufe: 'M' }} marke={company.showKreiseckLogo} renderQr={(d) => <QrSvg data={d} />} />
497
+ ```
498
+
499
+ ```ts
500
+ import { escPosLayoutBytes, logoMass, logoRaster } from '@kreiseck/kasseneck-api/receipt';
501
+
502
+ const mass = logoMass({ stufe: 'M', pxBreite: bild.width, pxHoehe: bild.height }, 48);
503
+ const raster = logoRaster(imageData.data, bild.width, bild.height, mass, 48);
504
+ escPosLayoutBytes(layout, { paperSize: 'mm80', logo: { stufe: 'M', pxBreite: bild.width, pxHoehe: bild.height, raster }, marke: true });
505
+ ```
506
+
507
+ Logo-Stufen: S 42 % × 5 Zeilen, M 62 % × 8, L 80 % × 12, XL 94 % × 16 — eingepasst,
508
+ nie hochgerechnet. Der Aufdruck (TESTKASSE, STORNOBELEG …) ist ein Rahmen aus
509
+ `=`-Zeilen, auf jedem Weg gleich.
510
+
486
511
  ## Hobex HPS über Kasseneck Connect
487
512
 
488
513
  Ein Browser hat weiterhin keine rohen TCP-Sockets — ein **direkter**
@@ -516,7 +541,8 @@ Android-SDKs ohne Entsprechung hier.
516
541
  ## Was hier grundsätzlich nicht dazugehört
517
542
 
518
543
  Die Druckeransteuerung selbst (dieses Paket erzeugt die Bytes, es verschickt
519
- sie nicht), Firmenlogos und Rasterbilder, und die PDF-Erzeugung.
544
+ sie nicht) und die PDF-Erzeugung. Bilder dekodieren (PNG/JPEG): das Paket
545
+ rastert fertige RGBA-Pixel, das Laden des Bilds bleibt bei der Anwendung.
520
546
 
521
547
  ## Entwicklung
522
548
 
@@ -2,6 +2,7 @@ import { ReceiptType, type ReceiptTypeKey, KeckPaymentMethod, type KeckPaymentMe
2
2
  import { type Receipt, type ReceiptCompany, type ReceiptItem, type Voucher, type ReceiptSummary, type ReportMonth, type CancellationItem, type CancellationOf, type CancellationReason } from '../models/index.js';
3
3
  import type { InternerTransport } from './aufrufe.js';
4
4
  import type { Pruefangaben, ReceiptLayout } from '../receipt/layout.js';
5
+ import type { LogoStufe } from '../receipt/blatt.js';
5
6
  /**
6
7
  * Beleg-Endpunkte — Zwilling der Beleg-Aufrufe in
7
8
  * kasseneck_api/lib/kasseneck_api.dart.
@@ -168,6 +169,12 @@ export interface ReceiptWithCompany {
168
169
  * fuer Clients, die das Layout selbst bauen; null bei altem Backend.
169
170
  */
170
171
  pruefangaben: Pruefangaben | null;
172
+ /**
173
+ * Groesse des Firmenlogos am Beleg (Kasse-Einstellung `logoSkala` des
174
+ * Betriebs). Bildschirm, Bon und PDF setzen das Logo in genau dieser Stufe;
175
+ * liefert das Backend sie nicht (alt), gilt `M` -- der Bestandswert.
176
+ */
177
+ logoStufe: LogoStufe;
171
178
  }
172
179
  /**
173
180
  * Gemeinsame Umsetzung aller Belegarten (Zwilling von `_createReceipt`).
@@ -582,5 +582,6 @@ function belegMitFirmaAusHuelle(daten, functionName) {
582
582
  kopfId: typeof d.kopfId === 'string' ? d.kopfId : null,
583
583
  layout,
584
584
  pruefangaben: pa ? { karteRegistriertAm: text(pa.karteRegistriertAm), kasseRegistriertAm: text(pa.kasseRegistriertAm) } : null,
585
+ logoStufe: d.logo_skala === 'S' || d.logo_skala === 'M' || d.logo_skala === 'L' || d.logo_skala === 'XL' ? d.logo_skala : 'M',
585
586
  };
586
587
  }
@@ -1,5 +1,6 @@
1
1
  import type { InternerTransport } from '../client/aufrufe.js';
2
2
  import type { ReceiptLayout } from '../receipt/layout.js';
3
+ import type { DruckLogo } from '../receipt/layout-escpos.js';
3
4
  /**
4
5
  * Netzwerk-Bondrucker ueber Epson "Server Direct Print": das Backend fuehrt
5
6
  * je Konto Drucker mit einer geheimen Abhol-URL; die Kasse legt Druckjobs
@@ -46,6 +47,10 @@ export interface CreatePrintJobOptions {
46
47
  receiptId?: string;
47
48
  titel?: string;
48
49
  quelle?: string;
50
+ /** Firmenlogo als fertiges Rasterbild (`logoRaster`); der Server dekodiert keine Bilder. */
51
+ logo?: DruckLogo | null;
52
+ /** "erstellt mit Kasseneck" am Ende (Konto-Flag `kreiseck_logo`). */
53
+ marke?: boolean;
49
54
  }
50
55
  export declare function createPrintJob(rufen: InternerTransport, o: CreatePrintJobOptions): Promise<DruckJob>;
51
56
  export declare function getPrintJob(rufen: InternerTransport, o: {
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.listMyPrinters = listMyPrinters;
4
4
  exports.createPrintJob = createPrintJob;
5
5
  exports.getPrintJob = getPrintJob;
6
+ const index_js_1 = require("../printing/index.js");
6
7
  const text = (v) => (typeof v === 'string' && v ? v : null);
7
8
  const zahl = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : null);
8
9
  async function listMyPrinters(rufen) {
@@ -27,6 +28,14 @@ async function createPrintJob(rufen, o) {
27
28
  params.titel = o.titel;
28
29
  if (o.quelle)
29
30
  params.quelle = o.quelle;
31
+ if (o.logo) {
32
+ params.logo = {
33
+ stufe: o.logo.stufe, pxBreite: o.logo.pxBreite, pxHoehe: o.logo.pxHoehe,
34
+ breite: o.logo.raster.breite, hoehe: o.logo.raster.hoehe, zeilen: (0, index_js_1.rasterZeilenBase64)(o.logo.raster),
35
+ };
36
+ }
37
+ if (o.marke === true)
38
+ params.marke = true;
30
39
  const daten = await rufen('createPrintJob', params);
31
40
  return { jobId: String(daten?.jobId ?? ''), status: text(daten?.status) ?? 'offen', ergebnis: null };
32
41
  }
@@ -116,8 +116,11 @@ exports.KASSE_TASTEN_STANDARD = Object.freeze({
116
116
  korbLeeren: ['Mod+C'],
117
117
  });
118
118
  exports.KASSE_BETRIEB_STANDARD = Object.freeze({
119
- // Petrol aus der Markenpalette ("Ecke, Aktion") — nicht das alte Blau.
120
- logoText: 'K', logoAn: true, logoGroesse: 'M', wasserzeichen: 'anmeldung', farbe: '#116B6B',
119
+ // Das Petrol der Marke: die Aktionsfarbe des Design-Systems (Rolle `brand`).
120
+ // Stand bis September 2026 auf dem Wert des alten Markenhandbuchs,
121
+ // der um 0,07 in OKLab danebenlag. Unsichtbar, aber es war die letzte Stelle
122
+ // im Haus, an der eine zweite Zahl fuer dieselbe Farbe stand.
123
+ logoText: 'K', logoAn: true, logoGroesse: 'M', wasserzeichen: 'anmeldung', farbe: '#136B6B',
121
124
  stil: 'klar', schrift: 'M', schriftEinst: 'S', kachelstil: 'streifen', uhr: true,
122
125
  sperrbild: true, foto: true, autoAbMin: 0, abNachVerkauf: false, schnellLogin: true,
123
126
  preisAnzeigen: true, ustAnzeigen: false, emoji: true, katFarben: true, freiErlaubt: true,
@@ -24,8 +24,9 @@
24
24
  * CP437-Plaetze umkodiert (ä = 0x84, ü = 0x81, ß = 0xE1, ...). Zeichen ohne
25
25
  * CP437-Platz werden zu `?` — weiterhin ein Byte je Zeichen.
26
26
  *
27
- * Nicht enthalten (bewusst): Rasterbilder/Logos, Capability-Profile einzelner
28
- * Druckermodelle, Kassenlade, 1D-Barcodes.
27
+ * Nicht enthalten (bewusst): Bilddekodierung (PNG/JPEG liest die Huelle),
28
+ * Capability-Profile einzelner Druckermodelle, Kassenlade, 1D-Barcodes.
29
+ * Fertige einfarbige Rasterbilder (Logo) gehen ueber [escPosRasterBild].
29
30
  */
30
31
  import { type QrModulGroesse } from './qr-groesse.js';
31
32
  /** Papierbreite der Bonrolle. */
@@ -103,6 +104,7 @@ export interface EscPosQrOptions {
103
104
  * die Regel in `qr-groesse.ts`.
104
105
  */
105
106
  size?: QrSize;
107
+ /** Fehlerkorrektur; Vorgabe `M` wie auf allen Druckwegen (siehe `qrCodeBytes`). */
106
108
  correction?: QrCorrection;
107
109
  /** Deckel fuer die gerechnete Modulgroesse; wirkungslos neben `size`. */
108
110
  groesse?: QrModulGroesse;
@@ -255,6 +257,12 @@ export declare function escPosRow(doc: EscPosDocument, columns: readonly PosColu
255
257
  * es wird kein Bild uebertragen.
256
258
  *
257
259
  * Bei Kasseneck-Belegen steht hier der maschinenlesbare RKSV-Code.
260
+ *
261
+ * Fehlerkorrektur ohne Angabe: **M** (bis 0.13: L). Die Groessenrechnung
262
+ * (`qrModulAnzahl`), das Blatt (Anteil am Bildschirm und im PDF), der
263
+ * ePOS-Weg (`level_m`) und der Bildweg rechnen alle mit M — druckte der
264
+ * native Befehl mit L, kaeme fuer manche Nutzlasten ein kleineres Symbol
265
+ * heraus als der Bildschirm zeigt.
258
266
  */
259
267
  export declare function qrCodeBytes(text: string, options?: {
260
268
  size?: QrSize;
@@ -266,8 +274,8 @@ export declare function qrCodeBytes(text: string, options?: {
266
274
  * **gerechneter** Modulgroesse, sofern `options.size` sie nicht festlegt.
267
275
  *
268
276
  * Ohne `size` entscheidet die Regel aus `qr-groesse.ts`: so gross wie
269
- * moeglich, gedeckelt durch `options.groesse` (Vorgabe `auto` = der
270
- * Bestandswert 4 dieses Pakets). Passt das Symbol auch mit der
277
+ * moeglich, gedeckelt durch `options.groesse` (Vorgabe `auto` = hoechstens 6
278
+ * Punkte je Modul, wie im Flutter-Zwilling). Passt das Symbol auch mit der
271
279
  * Ausnahmegroesse nicht aufs Papier, geht **kein** QR-Befehl hinaus und
272
280
  * `doc.qrFehler` sagt warum: der Drucker schneidet ein zu breites Symbol
273
281
  * nicht ab, er laesst es weg — ein Befehl, von dem man weiss, dass er nichts
@@ -300,4 +308,30 @@ export declare function qrRasterPunkte(paperSize: PosPaperSize, moduleAnzahl: nu
300
308
  groesse?: QrModulGroesse;
301
309
  ruhezoneModule?: number;
302
310
  }): number;
311
+ /**
312
+ * Einfarbiges Rasterbild in Druckpunkten, zeilenweise: `punkte[y * breite + x]`,
313
+ * 1 = schwarz. Entsteht fuer das Firmenlogo in `logoRaster` (receipt/bild.ts).
314
+ */
315
+ export interface RasterBild {
316
+ readonly breite: number;
317
+ readonly hoehe: number;
318
+ readonly punkte: Uint8Array;
319
+ }
320
+ /** Die Rasterzeilen als Bytes: MSB zuerst, jede Zeile auf volle Bytes aufgefuellt. */
321
+ export declare function rasterZeilenBytes(bild: RasterBild): Uint8Array;
322
+ /**
323
+ * Die Rasterzeilen als Base64 -- ohne Buffer, laeuft im Browser und in Node.
324
+ * Eine Stelle fuer ePOS-`<image>` und den Druckjob an den Server.
325
+ */
326
+ export declare function rasterZeilenBase64(bild: RasterBild): string;
327
+ /**
328
+ * Ein Rasterbild (`GS v 0`) -- das Firmenlogo am Bon.
329
+ *
330
+ * Anders als `escPosQrRaster` folgt KEIN Zeilenvorschub: `GS v 0` schiebt das
331
+ * Papier um die Bildhoehe, ein LF danach waere eine zusaetzliche Leerzeile,
332
+ * die Bildschirm und PDF nicht haben. Die Luft um das Logo kommt aus dem Blatt.
333
+ */
334
+ export declare function escPosRasterBild(doc: EscPosDocument, bild: RasterBild, options?: {
335
+ align?: PosAlign;
336
+ }): void;
303
337
  export {};
@@ -25,8 +25,9 @@
25
25
  * CP437-Plaetze umkodiert (ä = 0x84, ü = 0x81, ß = 0xE1, ...). Zeichen ohne
26
26
  * CP437-Platz werden zu `?` — weiterhin ein Byte je Zeichen.
27
27
  *
28
- * Nicht enthalten (bewusst): Rasterbilder/Logos, Capability-Profile einzelner
29
- * Druckermodelle, Kassenlade, 1D-Barcodes.
28
+ * Nicht enthalten (bewusst): Bilddekodierung (PNG/JPEG liest die Huelle),
29
+ * Capability-Profile einzelner Druckermodelle, Kassenlade, 1D-Barcodes.
30
+ * Fertige einfarbige Rasterbilder (Logo) gehen ueber [escPosRasterBild].
30
31
  */
31
32
  Object.defineProperty(exports, "__esModule", { value: true });
32
33
  exports.encodeEscPosText = encodeEscPosText;
@@ -49,6 +50,9 @@ exports.qrCodeBytes = qrCodeBytes;
49
50
  exports.escPosQrCode = escPosQrCode;
50
51
  exports.escPosQrRaster = escPosQrRaster;
51
52
  exports.qrRasterPunkte = qrRasterPunkte;
53
+ exports.rasterZeilenBytes = rasterZeilenBytes;
54
+ exports.rasterZeilenBase64 = rasterZeilenBase64;
55
+ exports.escPosRasterBild = escPosRasterBild;
52
56
  const qr_groesse_js_1 = require("./qr-groesse.js");
53
57
  // -------------------------------------------------------------- Befehlsbytes
54
58
  // Wortwoertlich aus commands.dart. Die Zahlen sind ASCII-Codes der dortigen
@@ -603,13 +607,19 @@ function escPosRow(doc, columns) {
603
607
  * es wird kein Bild uebertragen.
604
608
  *
605
609
  * Bei Kasseneck-Belegen steht hier der maschinenlesbare RKSV-Code.
610
+ *
611
+ * Fehlerkorrektur ohne Angabe: **M** (bis 0.13: L). Die Groessenrechnung
612
+ * (`qrModulAnzahl`), das Blatt (Anteil am Bildschirm und im PDF), der
613
+ * ePOS-Weg (`level_m`) und der Bildweg rechnen alle mit M — druckte der
614
+ * native Befehl mit L, kaeme fuer manche Nutzlasten ein kleineres Symbol
615
+ * heraus als der Bildschirm zeigt.
606
616
  */
607
617
  function qrCodeBytes(text, options = {}) {
608
618
  const size = options.size ?? 4;
609
619
  if (!istGanzzahl(size) || size < 1 || size > 8) {
610
620
  throw new Error('QR-Modulgroesse muss eine Ganzzahl im Bereich 1..8 sein');
611
621
  }
612
- const correction = options.correction ?? 'L';
622
+ const correction = options.correction ?? 'M';
613
623
  const stufe = QR_KORREKTUR[correction];
614
624
  if (stufe === undefined) {
615
625
  throw new Error(`Unbekannte QR-Fehlerkorrektur: ${String(correction)}`);
@@ -650,8 +660,8 @@ function qrCodeBytes(text, options = {}) {
650
660
  * **gerechneter** Modulgroesse, sofern `options.size` sie nicht festlegt.
651
661
  *
652
662
  * Ohne `size` entscheidet die Regel aus `qr-groesse.ts`: so gross wie
653
- * moeglich, gedeckelt durch `options.groesse` (Vorgabe `auto` = der
654
- * Bestandswert 4 dieses Pakets). Passt das Symbol auch mit der
663
+ * moeglich, gedeckelt durch `options.groesse` (Vorgabe `auto` = hoechstens 6
664
+ * Punkte je Modul, wie im Flutter-Zwilling). Passt das Symbol auch mit der
655
665
  * Ausnahmegroesse nicht aufs Papier, geht **kein** QR-Befehl hinaus und
656
666
  * `doc.qrFehler` sagt warum: der Drucker schneidet ein zu breites Symbol
657
667
  * nicht ab, er laesst es weg — ein Befehl, von dem man weiss, dass er nichts
@@ -736,9 +746,10 @@ function escPosQrRaster(doc, matrix, options = {}) {
736
746
  if (!istGanzzahl(punkte) || punkte < 1) {
737
747
  throw new Error('punkteJeModul muss eine Ganzzahl >= 1 sein');
738
748
  }
749
+ // Modulraster (samt Ruhezone) auf Druckpunkte skaliert -- dieselbe Bitquelle
750
+ // wie das Logo, nur aus einem QR-Modul-Bool statt aus Graustufen gewonnen.
739
751
  const breite = gesamtModule * punkte;
740
- const byteJeZeile = Math.ceil(breite / 8);
741
- const daten = new Uint8Array(byteJeZeile * breite);
752
+ const bildpunkte = new Uint8Array(breite * breite);
742
753
  for (let y = 0; y < breite; y++) {
743
754
  const modulY = Math.floor(y / punkte) - ruhezone;
744
755
  if (modulY < 0 || modulY >= module)
@@ -750,18 +761,14 @@ function escPosQrRaster(doc, matrix, options = {}) {
750
761
  continue;
751
762
  if (zeile[modulX] !== true)
752
763
  continue;
753
- const i = y * byteJeZeile + (x >> 3);
754
- daten[i] = daten[i] | (0x80 >> (x & 7));
764
+ bildpunkte[y * breite + x] = 1;
755
765
  }
756
766
  }
767
+ const daten = rasterZeilenBytes({ breite, hoehe: breite, punkte: bildpunkte });
757
768
  escPosSetStyles(doc, { align: options.align ?? 'center' });
758
769
  // GS v 0 m xL xH yL yH d1...dk — m = 0: normale Dichte, 1:1.
759
- anhaengen(doc, [
760
- GS, 0x76, 0x30, 0x00,
761
- byteJeZeile & 0xff, (byteJeZeile >> 8) & 0xff,
762
- breite & 0xff, (breite >> 8) & 0xff,
763
- ...daten,
764
- ]);
770
+ anhaengen(doc, rasterBildKopf(breite, breite));
771
+ anhaengen(doc, daten);
765
772
  anhaengen(doc, [ZEILENUMBRUCH]);
766
773
  if ((options.align ?? 'center') !== 'left') {
767
774
  escPosSetStyles(doc, { align: 'left' });
@@ -777,3 +784,68 @@ function qrRasterPunkte(paperSize, moduleAnzahl, options = {}) {
777
784
  const deckel = qr_groesse_js_1.QR_MODUL_DECKEL[options.groesse ?? 'auto'];
778
785
  return Math.max(1, Math.min(deckel, Math.floor(qr_groesse_js_1.QR_DRUCK_PUNKTE[paperSize] / (moduleAnzahl + 2 * ruhezone))));
779
786
  }
787
+ /** Die Rasterzeilen als Bytes: MSB zuerst, jede Zeile auf volle Bytes aufgefuellt. */
788
+ function rasterZeilenBytes(bild) {
789
+ if (!istGanzzahl(bild.breite) || bild.breite < 1 || !istGanzzahl(bild.hoehe) || bild.hoehe < 1) {
790
+ throw new Error('Rasterbild ohne gueltiges Mass');
791
+ }
792
+ if (bild.punkte.length !== bild.breite * bild.hoehe)
793
+ throw new Error('Rasterbild: Punkte passen nicht zum Mass');
794
+ const byteJeZeile = Math.ceil(bild.breite / 8);
795
+ const daten = new Uint8Array(byteJeZeile * bild.hoehe);
796
+ for (let y = 0; y < bild.hoehe; y++) {
797
+ for (let x = 0; x < bild.breite; x++) {
798
+ if (bild.punkte[y * bild.breite + x] !== 1)
799
+ continue;
800
+ const i = y * byteJeZeile + (x >> 3);
801
+ daten[i] = daten[i] | (0x80 >> (x & 7));
802
+ }
803
+ }
804
+ return daten;
805
+ }
806
+ /**
807
+ * Die Rasterzeilen als Base64 -- ohne Buffer, laeuft im Browser und in Node.
808
+ * Eine Stelle fuer ePOS-`<image>` und den Druckjob an den Server.
809
+ */
810
+ function rasterZeilenBase64(bild) {
811
+ const bytes = rasterZeilenBytes(bild);
812
+ let binaer = '';
813
+ for (let i = 0; i < bytes.length; i += 0x8000) {
814
+ binaer += String.fromCharCode(...bytes.subarray(i, i + 0x8000));
815
+ }
816
+ return btoa(binaer);
817
+ }
818
+ /**
819
+ * Der `GS v 0`-Kopf (Byte-Breite, Zeilenhoehe) -- die Rasterzeilen selbst
820
+ * haengt der Aufrufer an. Gemeinsame Rahmung fuer das Logo (`escPosRasterBild`)
821
+ * und den QR-Bildweg (`escPosQrRaster`): beide drucken dasselbe Bildkommando,
822
+ * nur mit unterschiedlichem Nachlauf (Zeilenvorschub ja/nein).
823
+ */
824
+ function rasterBildKopf(breite, hoehe) {
825
+ const byteJeZeile = Math.ceil(breite / 8);
826
+ return [GS, 0x76, 0x30, 0x00, byteJeZeile & 0xff, (byteJeZeile >> 8) & 0xff, hoehe & 0xff, (hoehe >> 8) & 0xff];
827
+ }
828
+ /**
829
+ * Ein Rasterbild (`GS v 0`) -- das Firmenlogo am Bon.
830
+ *
831
+ * Anders als `escPosQrRaster` folgt KEIN Zeilenvorschub: `GS v 0` schiebt das
832
+ * Papier um die Bildhoehe, ein LF danach waere eine zusaetzliche Leerzeile,
833
+ * die Bildschirm und PDF nicht haben. Die Luft um das Logo kommt aus dem Blatt.
834
+ */
835
+ function escPosRasterBild(doc, bild, options = {}) {
836
+ // Masse pruefen, BEVOR gepackt wird: ein zu breites Bild soll nicht erst
837
+ // Speicher fuer seine Rasterzeilen belegen. `GS v 0` traegt die Hoehe in zwei
838
+ // Bytes (yL yH) -- ueber 65535 Punkte liefe sie still ueber und der Drucker
839
+ // laese den Rest des Bilds als Befehle.
840
+ if (bild.breite > qr_groesse_js_1.QR_DRUCK_PUNKTE[doc.paperSize])
841
+ throw new Error('Rasterbild breiter als der Druckkopf');
842
+ if (bild.hoehe > 0xffff)
843
+ throw new Error('Rasterbild hoeher als 65535 Punkte');
844
+ const daten = rasterZeilenBytes(bild);
845
+ escPosSetStyles(doc, { align: options.align ?? 'center' });
846
+ anhaengen(doc, rasterBildKopf(bild.breite, bild.hoehe));
847
+ anhaengen(doc, daten);
848
+ if ((options.align ?? 'center') !== 'left') {
849
+ escPosSetStyles(doc, { align: 'left' });
850
+ }
851
+ }
@@ -1,4 +1,4 @@
1
- export { type PosPaperSize, type PosAlign, type PosFont, type PosCutMode, type PosCodeTable, type PosTextSize, type QrSize, type QrCorrection, type QrMatrix, type PosStyles, type PosColumn, type EscPosOptions, type EscPosTextOptions, type EscPosHrOptions, type EscPosQrOptions, type EscPosQrRasterOptions, type EscPosDocument, createEscPosDocument, escPosBytes, escPosReset, escPosSetGlobalCodeTable, escPosSetGlobalFont, escPosSetStyles, escPosText, escPosEmptyLines, escPosFeed, escPosCut, escPosHr, escPosRow, escPosQrCode, escPosQrRaster, qrRasterPunkte, encodeEscPosText, qrCodeBytes, escPosMaxCharsPerLine, escPosWortzeilen, wortzeilenText, } from './escpos.js';
2
- export { type QrModulGroesse, type QrGroesse, QR_MODUL_DECKEL, QR_RUHEZONE_MODULE, QR_MINDEST_PUNKTE, QR_AUSNAHME_PUNKTE, QR_HOECHST_PUNKTE, QR_DRUCK_PUNKTE, qrModulAnzahl, qrGroesseBerechnen, qrGroesseFuer, } from './qr-groesse.js';
1
+ export { type PosPaperSize, type PosAlign, type PosFont, type PosCutMode, type PosCodeTable, type PosTextSize, type QrSize, type QrCorrection, type QrMatrix, type PosStyles, type PosColumn, type EscPosOptions, type EscPosTextOptions, type EscPosHrOptions, type EscPosQrOptions, type EscPosQrRasterOptions, type EscPosDocument, createEscPosDocument, escPosBytes, escPosReset, escPosSetGlobalCodeTable, escPosSetGlobalFont, escPosSetStyles, escPosText, escPosEmptyLines, escPosFeed, escPosCut, escPosHr, escPosRow, escPosQrCode, escPosQrRaster, qrRasterPunkte, type RasterBild, rasterZeilenBytes, rasterZeilenBase64, escPosRasterBild, encodeEscPosText, qrCodeBytes, escPosMaxCharsPerLine, escPosWortzeilen, wortzeilenText, } from './escpos.js';
2
+ export { type QrModulGroesse, type QrGroesse, QR_MODUL_DECKEL, QR_RUHEZONE_MODULE, QR_MINDEST_PUNKTE, QR_AUSNAHME_PUNKTE, QR_HOECHST_PUNKTE, QR_DRUCK_PUNKTE, qrModulAnzahl, qrPasstInVersion, qrGroesseBerechnen, qrGroesseFuer, } from './qr-groesse.js';
3
3
  export { escPosPrintableText } from './printable.js';
4
4
  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, UsbTimeoutError, usbDeviceKey, usbFindPrinterEndpoint, usbWriteAll, usbConnectPrinter, usbPrint, usbDisconnect, } from './webusb.js';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.usbDisconnect = exports.usbPrint = exports.usbConnectPrinter = exports.usbWriteAll = exports.usbFindPrinterEndpoint = exports.usbDeviceKey = exports.UsbTimeoutError = exports.USB_CLASS_PRINTER = exports.USB_VENDOR_EPSON = exports.escPosPrintableText = exports.qrGroesseFuer = exports.qrGroesseBerechnen = exports.qrModulAnzahl = exports.QR_DRUCK_PUNKTE = exports.QR_HOECHST_PUNKTE = exports.QR_AUSNAHME_PUNKTE = exports.QR_MINDEST_PUNKTE = exports.QR_RUHEZONE_MODULE = exports.QR_MODUL_DECKEL = exports.wortzeilenText = exports.escPosWortzeilen = exports.escPosMaxCharsPerLine = exports.qrCodeBytes = exports.encodeEscPosText = exports.qrRasterPunkte = exports.escPosQrRaster = 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;
3
+ exports.usbDisconnect = exports.usbPrint = exports.usbConnectPrinter = exports.usbWriteAll = exports.usbFindPrinterEndpoint = exports.usbDeviceKey = exports.UsbTimeoutError = exports.USB_CLASS_PRINTER = exports.USB_VENDOR_EPSON = exports.escPosPrintableText = exports.qrGroesseFuer = exports.qrGroesseBerechnen = exports.qrPasstInVersion = exports.qrModulAnzahl = exports.QR_DRUCK_PUNKTE = exports.QR_HOECHST_PUNKTE = exports.QR_AUSNAHME_PUNKTE = exports.QR_MINDEST_PUNKTE = exports.QR_RUHEZONE_MODULE = exports.QR_MODUL_DECKEL = exports.wortzeilenText = exports.escPosWortzeilen = exports.escPosMaxCharsPerLine = exports.qrCodeBytes = exports.encodeEscPosText = exports.escPosRasterBild = exports.rasterZeilenBase64 = exports.rasterZeilenBytes = exports.qrRasterPunkte = exports.escPosQrRaster = 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
4
  var escpos_js_1 = require("./escpos.js");
5
5
  Object.defineProperty(exports, "createEscPosDocument", { enumerable: true, get: function () { return escpos_js_1.createEscPosDocument; } });
6
6
  Object.defineProperty(exports, "escPosBytes", { enumerable: true, get: function () { return escpos_js_1.escPosBytes; } });
@@ -17,6 +17,9 @@ Object.defineProperty(exports, "escPosRow", { enumerable: true, get: function ()
17
17
  Object.defineProperty(exports, "escPosQrCode", { enumerable: true, get: function () { return escpos_js_1.escPosQrCode; } });
18
18
  Object.defineProperty(exports, "escPosQrRaster", { enumerable: true, get: function () { return escpos_js_1.escPosQrRaster; } });
19
19
  Object.defineProperty(exports, "qrRasterPunkte", { enumerable: true, get: function () { return escpos_js_1.qrRasterPunkte; } });
20
+ Object.defineProperty(exports, "rasterZeilenBytes", { enumerable: true, get: function () { return escpos_js_1.rasterZeilenBytes; } });
21
+ Object.defineProperty(exports, "rasterZeilenBase64", { enumerable: true, get: function () { return escpos_js_1.rasterZeilenBase64; } });
22
+ Object.defineProperty(exports, "escPosRasterBild", { enumerable: true, get: function () { return escpos_js_1.escPosRasterBild; } });
20
23
  Object.defineProperty(exports, "encodeEscPosText", { enumerable: true, get: function () { return escpos_js_1.encodeEscPosText; } });
21
24
  Object.defineProperty(exports, "qrCodeBytes", { enumerable: true, get: function () { return escpos_js_1.qrCodeBytes; } });
22
25
  Object.defineProperty(exports, "escPosMaxCharsPerLine", { enumerable: true, get: function () { return escpos_js_1.escPosMaxCharsPerLine; } });
@@ -30,6 +33,7 @@ Object.defineProperty(exports, "QR_AUSNAHME_PUNKTE", { enumerable: true, get: fu
30
33
  Object.defineProperty(exports, "QR_HOECHST_PUNKTE", { enumerable: true, get: function () { return qr_groesse_js_1.QR_HOECHST_PUNKTE; } });
31
34
  Object.defineProperty(exports, "QR_DRUCK_PUNKTE", { enumerable: true, get: function () { return qr_groesse_js_1.QR_DRUCK_PUNKTE; } });
32
35
  Object.defineProperty(exports, "qrModulAnzahl", { enumerable: true, get: function () { return qr_groesse_js_1.qrModulAnzahl; } });
36
+ Object.defineProperty(exports, "qrPasstInVersion", { enumerable: true, get: function () { return qr_groesse_js_1.qrPasstInVersion; } });
33
37
  Object.defineProperty(exports, "qrGroesseBerechnen", { enumerable: true, get: function () { return qr_groesse_js_1.qrGroesseBerechnen; } });
34
38
  Object.defineProperty(exports, "qrGroesseFuer", { enumerable: true, get: function () { return qr_groesse_js_1.qrGroesseFuer; } });
35
39
  var printable_js_1 = require("./printable.js");
@@ -10,26 +10,21 @@ import type { PosPaperSize, QrSize } from './escpos.js';
10
10
  * und ein 58-mm-Kopf hat 384. Zu breit heisst bei den meisten Geraeten nicht
11
11
  * "abgeschnitten", sondern **gar kein QR** — auf einem Pflichtbeleg der
12
12
  * schlechteste aller Ausgaenge. (Im Flutter-Zwilling war genau das der
13
- * belegte Fehler; dieses Paket druckt seit jeher mit vier Punkten und blieb
14
- * darum verschont. Die Regel ist trotzdem dieselbe: sie deckelt auch eine
15
- * ausdruecklich gewaehlte groessere Modulgroesse gegen den Papierrand ab.)
13
+ * belegte Fehler.) Die Regel deckelt darum auch eine ausdruecklich gewaehlte
14
+ * groessere Modulgroesse gegen den Papierrand ab.
16
15
  */
17
16
  /**
18
17
  * Wie gross die Module des Beleg-QR werden duerfen — ein **Deckel**, keine
19
18
  * Vorgabe: gedruckt wird immer die groesste Groesse, die noch aufs Papier
20
19
  * passt, hoechstens aber diese hier.
21
20
  *
22
- * `auto` und `klein` decken beide bei 4 — das ist kein Versehen. 4 ist der
23
- * Wert, den der native Weg dieses Pakets seit jeher druckt
24
- * (`qrCodeBytes(..., size ?? 4)`); ohne diesen Deckel bekaeme jedes Geraet ab
25
- * sofort ungefragt einen groesseren QR als gestern. `auto` heisst also
26
- * "rechne, aber aendere den Bestand nicht".
27
- *
28
- * **Abweichung zum Flutter-Zwilling, bewusst:** dort deckelt `auto` bei 6,
29
- * weil dort 6 der Bestandswert ist. Die Regel ist in beiden Paketen
30
- * dieselbe — "so gross wie moeglich, hoechstens der Bestandswert" —, nur der
31
- * Bestandswert unterscheidet sich. `mittel` (6) und `gross` (8) sind in
32
- * beiden Paketen gleich; sie waehlt ein Mensch.
21
+ * `auto` heisst "gerechnet, hoechstens 6 Punkte je Modul" — in diesem Paket
22
+ * und im Flutter-Zwilling dasselbe. Bis 0.13 deckelte `auto` hier bei 4 (dem
23
+ * alten Wert des nativen ESC/POS-Wegs), in Dart bei 6; derselbe Beleg kam
24
+ * dadurch je nach Paket verschieden gross aus dem Drucker. Einheitlich gilt
25
+ * jetzt 6: der Wert von Dart und vom Epson-Weg, und ein groesseres Modul
26
+ * liest sich besser. `klein` (4) druckt den QR so gross wie frueher `auto`;
27
+ * `mittel` (6) und `gross` (8) waehlt ein Mensch.
33
28
  */
34
29
  export type QrModulGroesse = 'auto' | 'klein' | 'mittel' | 'gross';
35
30
  /** Groesste Modulgroesse in Druckpunkten, die der jeweilige Deckel zulaesst. */
@@ -82,19 +77,29 @@ export declare const QR_DRUCK_PUNKTE: Readonly<Record<PosPaperSize, number>>;
82
77
  /**
83
78
  * Modulanzahl, die `nutzlast` bei Fehlerkorrektur **M** braucht.
84
79
  *
85
- * Warum M, obwohl der native Befehl mit L druckt: M braucht bei gleicher
86
- * Nutzlast gleich viele oder mehr Module als L. Wer mit M rechnet und mit L
87
- * druckt, druckt nie breiter als gerechnet — die Rechnung ist konservativ,
88
- * nie knapp. Umgekehrt waere sie eine Rechnung, die aufgeht, und ein Symbol,
89
- * das ueber den Papierrand laeuft. Dasselbe gilt fuer die Byte-Zaehlung: hier
90
- * zaehlt UTF-8 (wie im Flutter-Zwilling), waehrend `qrCodeBytes` die Nutzlast
91
- * als Latin-1 sendet — UTF-8 ist nie kuerzer, die Rechnung also nie zu klein.
80
+ * Alle Druckwege setzen den QR mit Fehlerkorrektur **M** (nativer
81
+ * ESC/POS-Befehl, ePOS `level_m`; das Raster fuer den Bildweg rechnet der
82
+ * Aufrufer ebenfalls mit M) — rechnet und druckt also mit M: gerechnete und
83
+ * gedruckte Modulanzahl stimmen ueberein, und der Anteil am Blatt
84
+ * (Bildschirm, PDF) ist genau der am Bon. Die Byte-Zaehlung ist
85
+ * konservativ: hier zaehlt UTF-8 (wie im Flutter-Zwilling), waehrend
86
+ * `qrCodeBytes` die Nutzlast als Latin-1 sendet — UTF-8 ist nie kuerzer, die
87
+ * Rechnung also nie zu klein.
92
88
  *
93
89
  * Wirft, wenn die Nutzlast in keine Version passt — wie `qrCodeBytes` bei zu
94
90
  * langem Inhalt. Ein still zurueckgegebenes "passt nicht" haette den
95
91
  * Datenfehler als Papierfehler getarnt.
96
92
  */
97
93
  export declare function qrModulAnzahl(nutzlast: string): number;
94
+ /**
95
+ * Ob `nutzlast` in irgendeine QR-Version 1..40 bei Fehlerkorrektur M passt --
96
+ * dieselbe Tabelle wie `qrModulAnzahl`, aber ohne zu werfen.
97
+ *
98
+ * Fuer Aufrufer, denen ein zu langer Inhalt kein Programmierfehler ist,
99
+ * sondern ein Datenfehler, den sie selbst behandeln (das Beleg-Blatt: ohne
100
+ * QR weiterbauen statt den ganzen Zeichner mitzureissen).
101
+ */
102
+ export declare function qrPasstInVersion(nutzlast: string): boolean;
98
103
  /**
99
104
  * Groesste Modulgroesse, mit der `moduleAnzahl` Module **samt Ruhezone** in
100
105
  * `papierbreitePunkte` passen, gedeckelt durch `groesse`.
@@ -2,11 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.QR_DRUCK_PUNKTE = exports.QR_HOECHST_PUNKTE = exports.QR_AUSNAHME_PUNKTE = exports.QR_MINDEST_PUNKTE = exports.QR_RUHEZONE_MODULE = exports.QR_MODUL_DECKEL = void 0;
4
4
  exports.qrModulAnzahl = qrModulAnzahl;
5
+ exports.qrPasstInVersion = qrPasstInVersion;
5
6
  exports.qrGroesseBerechnen = qrGroesseBerechnen;
6
7
  exports.qrGroesseFuer = qrGroesseFuer;
7
8
  /** Groesste Modulgroesse in Druckpunkten, die der jeweilige Deckel zulaesst. */
8
9
  exports.QR_MODUL_DECKEL = {
9
- auto: 4,
10
+ auto: 6,
10
11
  klein: 4,
11
12
  mittel: 6,
12
13
  gross: 8,
@@ -49,13 +50,14 @@ const BYTE_KAPAZITAET_M = [
49
50
  /**
50
51
  * Modulanzahl, die `nutzlast` bei Fehlerkorrektur **M** braucht.
51
52
  *
52
- * Warum M, obwohl der native Befehl mit L druckt: M braucht bei gleicher
53
- * Nutzlast gleich viele oder mehr Module als L. Wer mit M rechnet und mit L
54
- * druckt, druckt nie breiter als gerechnet — die Rechnung ist konservativ,
55
- * nie knapp. Umgekehrt waere sie eine Rechnung, die aufgeht, und ein Symbol,
56
- * das ueber den Papierrand laeuft. Dasselbe gilt fuer die Byte-Zaehlung: hier
57
- * zaehlt UTF-8 (wie im Flutter-Zwilling), waehrend `qrCodeBytes` die Nutzlast
58
- * als Latin-1 sendet — UTF-8 ist nie kuerzer, die Rechnung also nie zu klein.
53
+ * Alle Druckwege setzen den QR mit Fehlerkorrektur **M** (nativer
54
+ * ESC/POS-Befehl, ePOS `level_m`; das Raster fuer den Bildweg rechnet der
55
+ * Aufrufer ebenfalls mit M) — rechnet und druckt also mit M: gerechnete und
56
+ * gedruckte Modulanzahl stimmen ueberein, und der Anteil am Blatt
57
+ * (Bildschirm, PDF) ist genau der am Bon. Die Byte-Zaehlung ist
58
+ * konservativ: hier zaehlt UTF-8 (wie im Flutter-Zwilling), waehrend
59
+ * `qrCodeBytes` die Nutzlast als Latin-1 sendet — UTF-8 ist nie kuerzer, die
60
+ * Rechnung also nie zu klein.
59
61
  *
60
62
  * Wirft, wenn die Nutzlast in keine Version passt — wie `qrCodeBytes` bei zu
61
63
  * langem Inhalt. Ein still zurueckgegebenes "passt nicht" haette den
@@ -69,6 +71,18 @@ function qrModulAnzahl(nutzlast) {
69
71
  }
70
72
  throw new Error('QR-Inhalt ist zu lang');
71
73
  }
74
+ /**
75
+ * Ob `nutzlast` in irgendeine QR-Version 1..40 bei Fehlerkorrektur M passt --
76
+ * dieselbe Tabelle wie `qrModulAnzahl`, aber ohne zu werfen.
77
+ *
78
+ * Fuer Aufrufer, denen ein zu langer Inhalt kein Programmierfehler ist,
79
+ * sondern ein Datenfehler, den sie selbst behandeln (das Beleg-Blatt: ohne
80
+ * QR weiterbauen statt den ganzen Zeichner mitzureissen).
81
+ */
82
+ function qrPasstInVersion(nutzlast) {
83
+ const laenge = new TextEncoder().encode(nutzlast).length;
84
+ return laenge <= BYTE_KAPAZITAET_M[BYTE_KAPAZITAET_M.length - 1];
85
+ }
72
86
  /**
73
87
  * Groesste Modulgroesse, mit der `moduleAnzahl` Module **samt Ruhezone** in
74
88
  * `papierbreitePunkte` passen, gedeckelt durch `groesse`.