@kreiseck/kasseneck-api 0.13.1 → 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.
- package/CHANGELOG.md +91 -0
- package/README.md +127 -21
- package/dist/cjs/client/auth.d.ts +4 -4
- package/dist/cjs/client/auth.js +3 -3
- package/dist/cjs/client/cashregisters.d.ts +1 -1
- package/dist/cjs/client/cashregisters.js +1 -1
- package/dist/cjs/client/errors.d.ts +1 -1
- package/dist/cjs/client/errors.js +2 -2
- package/dist/cjs/client/receipts.d.ts +8 -1
- package/dist/cjs/client/receipts.js +2 -1
- package/dist/cjs/client/transport.d.ts +1 -1
- package/dist/cjs/client/transport.js +2 -2
- package/dist/cjs/kasse/drucker.d.ts +5 -0
- package/dist/cjs/kasse/drucker.js +9 -0
- package/dist/cjs/kasse/settings.js +5 -2
- package/dist/cjs/models/cashregister.d.ts +2 -2
- package/dist/cjs/models/receipt-company.d.ts +1 -1
- package/dist/cjs/printing/escpos.d.ts +38 -4
- package/dist/cjs/printing/escpos.js +87 -15
- package/dist/cjs/printing/index.d.ts +2 -2
- package/dist/cjs/printing/index.js +5 -1
- package/dist/cjs/printing/qr-groesse.d.ts +26 -21
- package/dist/cjs/printing/qr-groesse.js +22 -8
- package/dist/cjs/react/index.d.ts +53 -0
- package/dist/cjs/react/index.js +81 -0
- package/dist/cjs/receipt/bild.d.ts +14 -0
- package/dist/cjs/receipt/bild.js +65 -0
- package/dist/cjs/receipt/blatt.d.ts +107 -0
- package/dist/cjs/receipt/blatt.js +137 -0
- package/dist/cjs/receipt/epos.d.ts +19 -8
- package/dist/cjs/receipt/epos.js +39 -20
- package/dist/cjs/receipt/grid.d.ts +1 -1
- package/dist/cjs/receipt/grid.js +9 -1
- package/dist/cjs/receipt/index.d.ts +4 -2
- package/dist/cjs/receipt/index.js +17 -1
- package/dist/cjs/receipt/layout-escpos.d.ts +31 -3
- package/dist/cjs/receipt/layout-escpos.js +58 -18
- package/dist/cjs/register/index.d.ts +1 -1
- package/dist/cjs/register/index.js +1 -1
- package/dist/cjs/register/pairing.d.ts +2 -2
- package/dist/esm/client/auth.d.ts +4 -4
- package/dist/esm/client/auth.js +3 -3
- package/dist/esm/client/cashregisters.d.ts +1 -1
- package/dist/esm/client/cashregisters.js +1 -1
- package/dist/esm/client/errors.d.ts +1 -1
- package/dist/esm/client/errors.js +2 -2
- package/dist/esm/client/receipts.d.ts +8 -1
- package/dist/esm/client/receipts.js +2 -1
- package/dist/esm/client/transport.d.ts +1 -1
- package/dist/esm/client/transport.js +2 -2
- package/dist/esm/kasse/drucker.d.ts +5 -0
- package/dist/esm/kasse/drucker.js +9 -0
- package/dist/esm/kasse/settings.js +5 -2
- package/dist/esm/models/cashregister.d.ts +2 -2
- package/dist/esm/models/receipt-company.d.ts +1 -1
- package/dist/esm/printing/escpos.d.ts +38 -4
- package/dist/esm/printing/escpos.js +84 -15
- package/dist/esm/printing/index.d.ts +2 -2
- package/dist/esm/printing/index.js +2 -2
- package/dist/esm/printing/qr-groesse.d.ts +26 -21
- package/dist/esm/printing/qr-groesse.js +21 -8
- package/dist/esm/react/index.d.ts +53 -0
- package/dist/esm/react/index.js +80 -1
- package/dist/esm/receipt/bild.d.ts +14 -0
- package/dist/esm/receipt/bild.js +62 -0
- package/dist/esm/receipt/blatt.d.ts +107 -0
- package/dist/esm/receipt/blatt.js +128 -0
- package/dist/esm/receipt/epos.d.ts +19 -8
- package/dist/esm/receipt/epos.js +40 -22
- package/dist/esm/receipt/grid.d.ts +1 -1
- package/dist/esm/receipt/grid.js +9 -1
- package/dist/esm/receipt/index.d.ts +4 -2
- package/dist/esm/receipt/index.js +4 -2
- package/dist/esm/receipt/layout-escpos.d.ts +31 -3
- package/dist/esm/receipt/layout-escpos.js +58 -20
- package/dist/esm/register/index.d.ts +1 -1
- package/dist/esm/register/index.js +1 -1
- package/dist/esm/register/pairing.d.ts +2 -2
- package/fixtures/erwartet/karte-eigener.blatt32.json +159 -0
- package/fixtures/erwartet/karte-eigener.blatt48.json +159 -0
- package/fixtures/erwartet/karte-gptom-ios.blatt32.json +231 -0
- package/fixtures/erwartet/karte-gptom-ios.blatt48.json +231 -0
- package/fixtures/erwartet/karte-gptom.blatt32.json +231 -0
- package/fixtures/erwartet/karte-gptom.blatt48.json +231 -0
- package/fixtures/erwartet/karte-hobex-cloud.blatt32.json +201 -0
- package/fixtures/erwartet/karte-hobex-cloud.blatt48.json +201 -0
- package/fixtures/erwartet/karte-hobex-hps.blatt32.json +225 -0
- package/fixtures/erwartet/karte-hobex-hps.blatt48.json +225 -0
- package/fixtures/erwartet/karte-mypos.blatt32.json +255 -0
- package/fixtures/erwartet/karte-mypos.blatt48.json +243 -0
- package/fixtures/erwartet/karte-stripe-eps.blatt32.json +195 -0
- package/fixtures/erwartet/karte-stripe-eps.blatt48.json +195 -0
- package/fixtures/erwartet/karte-stripe.blatt32.json +213 -0
- package/fixtures/erwartet/karte-stripe.blatt48.json +213 -0
- package/fixtures/erwartet/karte-sumup.blatt32.json +219 -0
- package/fixtures/erwartet/karte-sumup.blatt48.json +207 -0
- package/fixtures/erwartet/langer-artikelname.blatt32.json +177 -0
- package/fixtures/erwartet/langer-artikelname.blatt48.json +171 -0
- package/fixtures/erwartet/logo-probe-hoch.raster32.txt +120 -0
- package/fixtures/erwartet/logo-probe.raster32.txt +54 -0
- package/fixtures/erwartet/null-ausfall.blatt32.json +207 -0
- package/fixtures/erwartet/null-ausfall.blatt48.json +189 -0
- package/fixtures/erwartet/null-ausfall.grid32.txt +2 -0
- package/fixtures/erwartet/null-ausfall.grid48.txt +2 -0
- package/fixtures/erwartet/null-jahr.blatt32.json +213 -0
- package/fixtures/erwartet/null-jahr.blatt48.json +189 -0
- package/fixtures/erwartet/null-jahr.grid32.txt +2 -0
- package/fixtures/erwartet/null-jahr.grid48.txt +2 -0
- package/fixtures/erwartet/null-monat.blatt32.json +207 -0
- package/fixtures/erwartet/null-monat.blatt48.json +189 -0
- package/fixtures/erwartet/null-monat.grid32.txt +2 -0
- package/fixtures/erwartet/null-monat.grid48.txt +2 -0
- package/fixtures/erwartet/null-pruef.blatt32.json +207 -0
- package/fixtures/erwartet/null-pruef.blatt48.json +189 -0
- package/fixtures/erwartet/null-pruef.grid32.txt +2 -0
- package/fixtures/erwartet/null-pruef.grid48.txt +2 -0
- package/fixtures/erwartet/null-schluss.blatt32.json +207 -0
- package/fixtures/erwartet/null-schluss.blatt48.json +189 -0
- package/fixtures/erwartet/null-schluss.grid32.txt +2 -0
- package/fixtures/erwartet/null-schluss.grid48.txt +2 -0
- package/fixtures/erwartet/null-start.blatt32.json +207 -0
- package/fixtures/erwartet/null-start.blatt48.json +189 -0
- package/fixtures/erwartet/null-start.grid32.txt +2 -0
- package/fixtures/erwartet/null-start.grid48.txt +2 -0
- package/fixtures/erwartet/rabatt-chef-trinkgeld.blatt32.json +213 -0
- package/fixtures/erwartet/rabatt-chef-trinkgeld.blatt48.json +207 -0
- package/fixtures/erwartet/rabatt-einfach.blatt32.json +183 -0
- package/fixtures/erwartet/rabatt-einfach.blatt48.json +177 -0
- package/fixtures/erwartet/rabatt-trinkgeld.blatt32.json +213 -0
- package/fixtures/erwartet/rabatt-trinkgeld.blatt48.json +207 -0
- package/fixtures/erwartet/rabatt-wertgutschein.blatt32.json +219 -0
- package/fixtures/erwartet/rabatt-wertgutschein.blatt48.json +213 -0
- package/fixtures/erwartet/rabattzeilen.blatt32.json +201 -0
- package/fixtures/erwartet/rabattzeilen.blatt48.json +195 -0
- package/fixtures/erwartet/signaturausfall-verkauf.blatt32.json +195 -0
- package/fixtures/erwartet/signaturausfall-verkauf.blatt48.json +183 -0
- package/fixtures/erwartet/storno-rabatt.blatt32.json +249 -0
- package/fixtures/erwartet/storno-rabatt.blatt48.json +237 -0
- package/fixtures/erwartet/storno-rabatt.grid32.txt +2 -0
- package/fixtures/erwartet/storno-rabatt.grid48.txt +2 -0
- package/fixtures/erwartet/storno-teil.blatt32.json +207 -0
- package/fixtures/erwartet/storno-teil.blatt48.json +201 -0
- package/fixtures/erwartet/storno-teil.grid32.txt +2 -0
- package/fixtures/erwartet/storno-teil.grid48.txt +2 -0
- package/fixtures/erwartet/storno-voll.blatt32.json +219 -0
- package/fixtures/erwartet/storno-voll.blatt48.json +213 -0
- package/fixtures/erwartet/storno-voll.grid32.txt +2 -0
- package/fixtures/erwartet/storno-voll.grid48.txt +2 -0
- package/fixtures/erwartet/testkasse-verkauf.blatt32.json +225 -0
- package/fixtures/erwartet/testkasse-verkauf.blatt48.json +219 -0
- package/fixtures/erwartet/testkasse-verkauf.grid32.txt +5 -1
- package/fixtures/erwartet/testkasse-verkauf.grid48.txt +5 -1
- package/fixtures/erwartet/testsignatur-verkauf.blatt32.json +237 -0
- package/fixtures/erwartet/testsignatur-verkauf.blatt48.json +219 -0
- package/fixtures/erwartet/testsignatur-verkauf.grid32.txt +5 -1
- package/fixtures/erwartet/testsignatur-verkauf.grid48.txt +5 -1
- package/fixtures/erwartet/training.blatt32.json +237 -0
- package/fixtures/erwartet/training.blatt48.json +219 -0
- package/fixtures/erwartet/training.grid32.txt +2 -0
- package/fixtures/erwartet/training.grid48.txt +2 -0
- package/fixtures/erwartet/verkauf-bar.blatt32.json +177 -0
- package/fixtures/erwartet/verkauf-bar.blatt48.json +171 -0
- package/fixtures/erwartet/verkauf-karte.blatt32.json +177 -0
- package/fixtures/erwartet/verkauf-karte.blatt48.json +171 -0
- package/fixtures/erwartet/verkauf-kleinunternehmer.blatt32.json +183 -0
- package/fixtures/erwartet/verkauf-kleinunternehmer.blatt48.json +177 -0
- package/fixtures/hobex-hps-codes.json +1 -1
- package/fixtures/kasse-settings-standard.json +1 -1
- package/fixtures/kasse-texte.json +1 -1
- package/fixtures/manifest.json +109 -43
- package/fixtures/oberflaeche.json +1 -1
- package/package.json +20 -5
|
@@ -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):
|
|
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 ?? '
|
|
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` =
|
|
654
|
-
*
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
14
|
-
*
|
|
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`
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
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
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
* zaehlt UTF-8 (wie im Flutter-Zwilling), waehrend
|
|
91
|
-
* als Latin-1 sendet — UTF-8 ist nie kuerzer, die
|
|
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:
|
|
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
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* zaehlt UTF-8 (wie im Flutter-Zwilling), waehrend
|
|
58
|
-
* als Latin-1 sendet — UTF-8 ist nie kuerzer, die
|
|
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`.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import type { ReceiptLayout } from '../receipt/layout.js';
|
|
3
|
+
import { type BelegBlatt, type LogoStufe } from '../receipt/blatt.js';
|
|
4
|
+
import type { QrModulGroesse } from '../printing/qr-groesse.js';
|
|
3
5
|
/**
|
|
4
6
|
* React-Adapter: zeichnet ein Beleg-Layout (siehe ../receipt/layout.ts).
|
|
5
7
|
*
|
|
@@ -33,6 +35,11 @@ export interface ReceiptLayoutViewProps {
|
|
|
33
35
|
/** Text auf dem verdeckten QR (Vorgabe „Antippen zum Anzeigen“). */
|
|
34
36
|
qrVerdecktText?: string;
|
|
35
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* @deprecated Seit 0.14.0: [BelegBlattView] setzt den Beleg zeichengleich zu
|
|
40
|
+
* Bon und PDF (Raster, Logo, Marke). Diese Ansicht rechnet Spalten mit Flex
|
|
41
|
+
* und bricht darum anders um als das Papier.
|
|
42
|
+
*/
|
|
36
43
|
export declare function ReceiptLayoutView({ layout, className, renderQr, qrVerdeckt, qrVerdecktText }: ReceiptLayoutViewProps): ReactNode;
|
|
37
44
|
/**
|
|
38
45
|
* Verdeckter QR: weichgezeichnet und nicht scannbar, bis der Betrachter ihn
|
|
@@ -44,3 +51,49 @@ export declare function QrVerdeckt({ data, text, children }: {
|
|
|
44
51
|
text?: string;
|
|
45
52
|
children: ReactNode;
|
|
46
53
|
}): ReactNode;
|
|
54
|
+
export interface BelegBlattZeilenProps {
|
|
55
|
+
blatt: BelegBlatt;
|
|
56
|
+
/** Adresse des Firmenlogos; ohne sie bleibt der Logo-Block leer (Platz bleibt). */
|
|
57
|
+
logoUrl?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Zeichnet den QR in seinen Kasten (`qrBlattAnteil`). Der Kasten schliesst
|
|
60
|
+
* die Ruhezone von 4 Modulen je Seite ein und setzt Fehlerkorrektur M
|
|
61
|
+
* voraus: das Symbol also mit Korrektur M und 4 Modulen Ruhezone zeichnen
|
|
62
|
+
* und den Kasten ganz ausfuellen -- dann ist ein Modul so gross wie am Bon.
|
|
63
|
+
*/
|
|
64
|
+
renderQr?: (data: string) => ReactNode;
|
|
65
|
+
qrVerdeckt?: boolean;
|
|
66
|
+
qrVerdecktText?: string;
|
|
67
|
+
className?: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Das Blatt am Bildschirm -- Zeile fuer Zeile dieselben Zeichen wie am Bon und
|
|
71
|
+
* im PDF. Masse in `ch`: eine Zeichenbreite ist `1ch`, eine Zeile `2ch`, das
|
|
72
|
+
* Blatt `zeichen`ch breit. Der Verbraucher bestimmt nur Schrift (monospace,
|
|
73
|
+
* Vorgabe ueber `--keck-blatt-schrift`) und Schriftgroesse; alles andere steht
|
|
74
|
+
* im Blatt.
|
|
75
|
+
*/
|
|
76
|
+
export declare function BelegBlattZeilen({ blatt, logoUrl, renderQr, qrVerdeckt, qrVerdecktText, className }: BelegBlattZeilenProps): ReactNode;
|
|
77
|
+
export interface BelegBlattViewProps extends Omit<BelegBlattZeilenProps, 'blatt' | 'logoUrl'> {
|
|
78
|
+
layout: ReceiptLayout;
|
|
79
|
+
zeichen?: number;
|
|
80
|
+
/** Firmenlogo und Stufe (`logoSkala`); das Pixelmass liest die Ansicht selbst. */
|
|
81
|
+
logo?: {
|
|
82
|
+
url: string;
|
|
83
|
+
stufe: LogoStufe;
|
|
84
|
+
} | null;
|
|
85
|
+
marke?: boolean;
|
|
86
|
+
/** Geraete-Einstellung fuer die QR-Modulgroesse; Vorgabe `auto` (hoechstens 6 Punkte je Modul) — wie die Druckwege. */
|
|
87
|
+
qrGroesse?: QrModulGroesse;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Laedt das Logo (fuer sein Pixelmass), baut das Blatt und zeichnet es. Bis
|
|
91
|
+
* das Bild geladen ist, fehlt der Logo-Block -- die Kasse laedt das Logo ohnehin
|
|
92
|
+
* vorab in den Browser-Cache.
|
|
93
|
+
*
|
|
94
|
+
* Ein Logo ueber [logoPixelZulaessig] (4096x4096px, dieselbe Grenze wie das
|
|
95
|
+
* Druck-Kit beim Rastern fuer den Bon) bleibt hier ebenso ohne Logo-Block --
|
|
96
|
+
* sonst zeigte der Bildschirm ein Logo, das nie gedruckt wird: Bildschirm und
|
|
97
|
+
* Bon zeigen dasselbe Logo.
|
|
98
|
+
*/
|
|
99
|
+
export declare function BelegBlattView({ layout, zeichen, logo, marke, qrGroesse, ...rest }: BelegBlattViewProps): ReactNode;
|
package/dist/cjs/react/index.js
CHANGED
|
@@ -2,13 +2,21 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ReceiptLayoutView = ReceiptLayoutView;
|
|
4
4
|
exports.QrVerdeckt = QrVerdeckt;
|
|
5
|
+
exports.BelegBlattZeilen = BelegBlattZeilen;
|
|
6
|
+
exports.BelegBlattView = BelegBlattView;
|
|
5
7
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
8
|
const react_1 = require("react");
|
|
9
|
+
const blatt_js_1 = require("../receipt/blatt.js");
|
|
7
10
|
const AUSRICHTUNG = {
|
|
8
11
|
left: 'left',
|
|
9
12
|
center: 'center',
|
|
10
13
|
right: 'right',
|
|
11
14
|
};
|
|
15
|
+
/**
|
|
16
|
+
* @deprecated Seit 0.14.0: [BelegBlattView] setzt den Beleg zeichengleich zu
|
|
17
|
+
* Bon und PDF (Raster, Logo, Marke). Diese Ansicht rechnet Spalten mit Flex
|
|
18
|
+
* und bricht darum anders um als das Papier.
|
|
19
|
+
*/
|
|
12
20
|
function ReceiptLayoutView({ layout, className, renderQr, qrVerdeckt = false, qrVerdecktText }) {
|
|
13
21
|
const klasse = className === undefined ? 'keck-receipt' : `keck-receipt ${className}`;
|
|
14
22
|
return ((0, jsx_runtime_1.jsx)("div", { className: klasse, "data-paper-size": layout.paperSize, children: layout.lines.map((zeile, index) => ((0, jsx_runtime_1.jsx)(Zeile, { zeile: zeile, renderQr: renderQr, qrVerdeckt: qrVerdeckt, qrVerdecktText: qrVerdecktText }, index))) }));
|
|
@@ -59,3 +67,76 @@ function Zeile({ zeile, renderQr, qrVerdeckt, qrVerdecktText }) {
|
|
|
59
67
|
}
|
|
60
68
|
}
|
|
61
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Das Blatt am Bildschirm -- Zeile fuer Zeile dieselben Zeichen wie am Bon und
|
|
72
|
+
* im PDF. Masse in `ch`: eine Zeichenbreite ist `1ch`, eine Zeile `2ch`, das
|
|
73
|
+
* Blatt `zeichen`ch breit. Der Verbraucher bestimmt nur Schrift (monospace,
|
|
74
|
+
* Vorgabe ueber `--keck-blatt-schrift`) und Schriftgroesse; alles andere steht
|
|
75
|
+
* im Blatt.
|
|
76
|
+
*/
|
|
77
|
+
function BelegBlattZeilen({ blatt, logoUrl, renderQr, qrVerdeckt = false, qrVerdecktText, className }) {
|
|
78
|
+
const z = blatt.zeichen;
|
|
79
|
+
const klasse = className === undefined ? 'keck-blatt' : `keck-blatt ${className}`;
|
|
80
|
+
const blattStil = {
|
|
81
|
+
width: `${z}ch`,
|
|
82
|
+
fontFamily: 'var(--keck-blatt-schrift, "DM Mono", ui-monospace, Menlo, Consolas, monospace)',
|
|
83
|
+
fontVariantLigatures: 'none',
|
|
84
|
+
};
|
|
85
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: klasse, "data-zeichen": z, style: blattStil, children: blatt.bloecke.map((b, i) => {
|
|
86
|
+
switch (b.art) {
|
|
87
|
+
case 'zeile':
|
|
88
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "keck-blatt-zeile", style: { whiteSpace: 'pre', height: '2ch', lineHeight: '2ch', overflow: 'hidden', fontWeight: b.fett ? 'bold' : 'normal' }, children: b.text }, i));
|
|
89
|
+
case 'logo':
|
|
90
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "keck-blatt-logo", style: { height: `${b.hoeheZeilen * 2}ch`, display: 'flex', justifyContent: 'center' }, children: logoUrl === undefined ? null : ((0, jsx_runtime_1.jsx)("img", { src: logoUrl, alt: "", "aria-hidden": "true", style: { width: `${b.breiteAnteil * z}ch`, height: `${b.hoeheZeilen * 2}ch`, objectFit: 'contain' } })) }, i));
|
|
91
|
+
case 'qr': {
|
|
92
|
+
// Auch beim Anteil 0 (leer oder in keine Version passend) bekommt
|
|
93
|
+
// `renderQr` die Nutzlast: die Oberflaeche muss sagen koennen, dass
|
|
94
|
+
// der QR fehlt und ein Papierbeleg noetig ist. Bon und PDF lassen
|
|
95
|
+
// den QR dann weg und melden es ueber `qrFehler`.
|
|
96
|
+
const bild = renderQr !== undefined ? renderQr(b.nutzlast) : (0, jsx_runtime_1.jsx)("div", { "data-qr": b.nutzlast, "aria-label": "RKSV-QR-Code" });
|
|
97
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "keck-blatt-qr", style: { display: 'flex', justifyContent: 'center' }, children: (0, jsx_runtime_1.jsx)("div", { style: { width: `${b.breiteAnteil * z}ch`, aspectRatio: '1 / 1' }, children: qrVerdeckt ? (0, jsx_runtime_1.jsx)(QrVerdeckt, { data: b.nutzlast, text: qrVerdecktText, children: bild }) : bild }) }, i));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}) }));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Laedt das Logo (fuer sein Pixelmass), baut das Blatt und zeichnet es. Bis
|
|
104
|
+
* das Bild geladen ist, fehlt der Logo-Block -- die Kasse laedt das Logo ohnehin
|
|
105
|
+
* vorab in den Browser-Cache.
|
|
106
|
+
*
|
|
107
|
+
* Ein Logo ueber [logoPixelZulaessig] (4096x4096px, dieselbe Grenze wie das
|
|
108
|
+
* Druck-Kit beim Rastern fuer den Bon) bleibt hier ebenso ohne Logo-Block --
|
|
109
|
+
* sonst zeigte der Bildschirm ein Logo, das nie gedruckt wird: Bildschirm und
|
|
110
|
+
* Bon zeigen dasselbe Logo.
|
|
111
|
+
*/
|
|
112
|
+
function BelegBlattView({ layout, zeichen, logo, marke = false, qrGroesse, ...rest }) {
|
|
113
|
+
const [mass, setMass] = (0, react_1.useState)(null);
|
|
114
|
+
const url = logo?.url;
|
|
115
|
+
(0, react_1.useEffect)(() => {
|
|
116
|
+
if (url === undefined)
|
|
117
|
+
return undefined;
|
|
118
|
+
let aktiv = true;
|
|
119
|
+
const Bild = globalThis.Image;
|
|
120
|
+
if (Bild === undefined)
|
|
121
|
+
return undefined;
|
|
122
|
+
const bild = new Bild();
|
|
123
|
+
bild.onload = () => {
|
|
124
|
+
if (aktiv && (0, blatt_js_1.logoPixelZulaessig)(bild.naturalWidth, bild.naturalHeight))
|
|
125
|
+
setMass({ url, breite: bild.naturalWidth, hoehe: bild.naturalHeight });
|
|
126
|
+
};
|
|
127
|
+
bild.src = url;
|
|
128
|
+
return () => {
|
|
129
|
+
aktiv = false;
|
|
130
|
+
};
|
|
131
|
+
}, [url]);
|
|
132
|
+
const optionen = { marke };
|
|
133
|
+
if (zeichen !== undefined)
|
|
134
|
+
optionen.zeichen = zeichen;
|
|
135
|
+
if (qrGroesse !== undefined)
|
|
136
|
+
optionen.qrGroesse = qrGroesse;
|
|
137
|
+
const geladen = logo != null && mass !== null && mass.url === logo.url;
|
|
138
|
+
if (geladen)
|
|
139
|
+
optionen.logo = { stufe: logo.stufe, pxBreite: mass.breite, pxHoehe: mass.hoehe };
|
|
140
|
+
const blatt = (0, blatt_js_1.belegBlatt)(layout, optionen);
|
|
141
|
+
return geladen ? (0, jsx_runtime_1.jsx)(BelegBlattZeilen, { blatt: blatt, logoUrl: logo.url, ...rest }) : (0, jsx_runtime_1.jsx)(BelegBlattZeilen, { blatt: blatt, ...rest });
|
|
142
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { RasterBild } from '../printing/escpos.js';
|
|
2
|
+
import { type LogoMass } from './blatt.js';
|
|
3
|
+
/**
|
|
4
|
+
* RGBA-Pixel (wie `ImageData.data` im Browser oder ein dekodiertes PNG in
|
|
5
|
+
* Node/Dart) -> einfarbiges Rasterbild in genau der Groesse, die das Blatt
|
|
6
|
+
* dem Logo gibt.
|
|
7
|
+
*
|
|
8
|
+
* Die Rechnung ist Vertrag und hat einen Dart-Zwilling (Golden
|
|
9
|
+
* `erwartet/logo-probe.raster32.txt`): Flaechenmittel je Druckpunkt,
|
|
10
|
+
* Durchsichtiges auf Papierweiss, Helligkeit nach BT.601, Floyd-Steinberg mit
|
|
11
|
+
* Schwelle 128. Die Reihenfolge der Rechenschritte nicht aendern -- beide
|
|
12
|
+
* Sprachen rechnen mit IEEE-Doubles und kommen nur so auf dieselben Punkte.
|
|
13
|
+
*/
|
|
14
|
+
export declare function logoRaster(rgba: ArrayLike<number>, pxBreite: number, pxHoehe: number, mass: LogoMass, zeichen: number): RasterBild;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logoRaster = logoRaster;
|
|
4
|
+
const blatt_js_1 = require("./blatt.js");
|
|
5
|
+
/**
|
|
6
|
+
* RGBA-Pixel (wie `ImageData.data` im Browser oder ein dekodiertes PNG in
|
|
7
|
+
* Node/Dart) -> einfarbiges Rasterbild in genau der Groesse, die das Blatt
|
|
8
|
+
* dem Logo gibt.
|
|
9
|
+
*
|
|
10
|
+
* Die Rechnung ist Vertrag und hat einen Dart-Zwilling (Golden
|
|
11
|
+
* `erwartet/logo-probe.raster32.txt`): Flaechenmittel je Druckpunkt,
|
|
12
|
+
* Durchsichtiges auf Papierweiss, Helligkeit nach BT.601, Floyd-Steinberg mit
|
|
13
|
+
* Schwelle 128. Die Reihenfolge der Rechenschritte nicht aendern -- beide
|
|
14
|
+
* Sprachen rechnen mit IEEE-Doubles und kommen nur so auf dieselben Punkte.
|
|
15
|
+
*/
|
|
16
|
+
function logoRaster(rgba, pxBreite, pxHoehe, mass, zeichen) {
|
|
17
|
+
if (!Number.isInteger(pxBreite) || !Number.isInteger(pxHoehe) || pxBreite < 1 || pxHoehe < 1 || rgba.length !== pxBreite * pxHoehe * 4) {
|
|
18
|
+
throw new Error('RGBA-Laenge passt nicht zum Pixelmass');
|
|
19
|
+
}
|
|
20
|
+
const { breite, hoehe } = (0, blatt_js_1.logoRasterMass)(mass, zeichen);
|
|
21
|
+
const grau = new Float64Array(breite * hoehe);
|
|
22
|
+
const sx = pxBreite / breite;
|
|
23
|
+
const sy = pxHoehe / hoehe;
|
|
24
|
+
for (let y = 0; y < hoehe; y++) {
|
|
25
|
+
const y0 = Math.floor(y * sy);
|
|
26
|
+
const y1 = Math.min(pxHoehe, Math.max(y0 + 1, Math.floor((y + 1) * sy)));
|
|
27
|
+
for (let x = 0; x < breite; x++) {
|
|
28
|
+
const x0 = Math.floor(x * sx);
|
|
29
|
+
const x1 = Math.min(pxBreite, Math.max(x0 + 1, Math.floor((x + 1) * sx)));
|
|
30
|
+
let summe = 0;
|
|
31
|
+
let anzahl = 0;
|
|
32
|
+
for (let py = y0; py < y1; py++) {
|
|
33
|
+
for (let px = x0; px < x1; px++) {
|
|
34
|
+
const i = (py * pxBreite + px) * 4;
|
|
35
|
+
const deckung = rgba[i + 3] / 255;
|
|
36
|
+
const hell = 0.299 * rgba[i] + 0.587 * rgba[i + 1] + 0.114 * rgba[i + 2];
|
|
37
|
+
summe += hell * deckung + 255 * (1 - deckung);
|
|
38
|
+
anzahl += 1;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
grau[y * breite + x] = anzahl === 0 ? 255 : summe / anzahl;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const punkte = new Uint8Array(breite * hoehe);
|
|
45
|
+
for (let y = 0; y < hoehe; y++) {
|
|
46
|
+
for (let x = 0; x < breite; x++) {
|
|
47
|
+
const i = y * breite + x;
|
|
48
|
+
const alt = grau[i];
|
|
49
|
+
const neu = alt < 128 ? 0 : 255;
|
|
50
|
+
if (neu === 0)
|
|
51
|
+
punkte[i] = 1;
|
|
52
|
+
const fehler = alt - neu;
|
|
53
|
+
if (x + 1 < breite)
|
|
54
|
+
grau[i + 1] = grau[i + 1] + (fehler * 7) / 16;
|
|
55
|
+
if (y + 1 < hoehe) {
|
|
56
|
+
if (x > 0)
|
|
57
|
+
grau[i + breite - 1] = grau[i + breite - 1] + (fehler * 3) / 16;
|
|
58
|
+
grau[i + breite] = grau[i + breite] + (fehler * 5) / 16;
|
|
59
|
+
if (x + 1 < breite)
|
|
60
|
+
grau[i + breite + 1] = grau[i + breite + 1] + fehler / 16;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return { breite, hoehe, punkte };
|
|
65
|
+
}
|