@kreiseck/kasseneck-api 1.0.0 → 1.1.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 +35 -0
- package/dist/cjs/pos/texte.d.ts +32 -0
- package/dist/cjs/pos/texte.js +16 -0
- package/dist/cjs/printing/code-tables.d.ts +77 -0
- package/dist/cjs/printing/code-tables.js +224 -0
- package/dist/cjs/printing/escpos.d.ts +19 -6
- package/dist/cjs/printing/escpos.js +27 -48
- package/dist/cjs/printing/index.d.ts +1 -0
- package/dist/cjs/printing/index.js +6 -1
- package/dist/cjs/printing/printable.d.ts +14 -2
- package/dist/cjs/printing/printable.js +36 -2
- package/dist/cjs/react/index.js +7 -0
- package/dist/cjs/receipt/blatt.d.ts +9 -0
- package/dist/cjs/receipt/code-table-reference-data.d.ts +6 -0
- package/dist/cjs/receipt/code-table-reference-data.js +11 -0
- package/dist/cjs/receipt/code-table-test-sheet.d.ts +52 -0
- package/dist/cjs/receipt/code-table-test-sheet.js +153 -0
- package/dist/cjs/receipt/index.d.ts +1 -0
- package/dist/cjs/receipt/index.js +6 -1
- package/dist/cjs/receipt/layout-escpos.d.ts +6 -1
- package/dist/cjs/receipt/layout-escpos.js +11 -7
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/pos/texte.d.ts +32 -0
- package/dist/esm/pos/texte.js +16 -0
- package/dist/esm/printing/code-tables.d.ts +77 -0
- package/dist/esm/printing/code-tables.js +215 -0
- package/dist/esm/printing/escpos.d.ts +19 -6
- package/dist/esm/printing/escpos.js +27 -48
- package/dist/esm/printing/index.d.ts +1 -0
- package/dist/esm/printing/index.js +1 -0
- package/dist/esm/printing/printable.d.ts +14 -2
- package/dist/esm/printing/printable.js +36 -2
- package/dist/esm/react/index.js +7 -0
- package/dist/esm/receipt/blatt.d.ts +9 -0
- package/dist/esm/receipt/code-table-reference-data.d.ts +6 -0
- package/dist/esm/receipt/code-table-reference-data.js +8 -0
- package/dist/esm/receipt/code-table-test-sheet.d.ts +52 -0
- package/dist/esm/receipt/code-table-test-sheet.js +147 -0
- package/dist/esm/receipt/index.d.ts +1 -0
- package/dist/esm/receipt/index.js +1 -0
- package/dist/esm/receipt/layout-escpos.d.ts +6 -1
- package/dist/esm/receipt/layout-escpos.js +11 -7
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/fixtures/code-table-receipts.json +84 -0
- package/fixtures/code-tables.json +12 -0
- package/fixtures/expected/code-table-receipt.long-item-name.iso8859_15.hex +27 -0
- package/fixtures/expected/code-table-receipt.long-item-name.pc437.hex +27 -0
- package/fixtures/expected/code-table-receipt.long-item-name.pc850.hex +27 -0
- package/fixtures/expected/code-table-receipt.long-item-name.pc858.hex +27 -0
- package/fixtures/expected/code-table-receipt.long-item-name.replacement.hex +27 -0
- package/fixtures/expected/code-table-receipt.long-item-name.wpc1252.hex +27 -0
- package/fixtures/expected/code-table-receipt.sale-cash.iso8859_15.hex +34 -0
- package/fixtures/expected/code-table-receipt.sale-cash.pc437.hex +34 -0
- package/fixtures/expected/code-table-receipt.sale-cash.pc850.hex +34 -0
- package/fixtures/expected/code-table-receipt.sale-cash.pc858.hex +34 -0
- package/fixtures/expected/code-table-receipt.sale-cash.replacement.hex +34 -0
- package/fixtures/expected/code-table-receipt.sale-cash.wpc1252.hex +34 -0
- package/fixtures/expected/code-table-receipt.special-characters.iso8859_15.hex +30 -0
- package/fixtures/expected/code-table-receipt.special-characters.pc437.hex +30 -0
- package/fixtures/expected/code-table-receipt.special-characters.pc850.hex +30 -0
- package/fixtures/expected/code-table-receipt.special-characters.pc858.hex +30 -0
- package/fixtures/expected/code-table-receipt.special-characters.replacement.hex +30 -0
- package/fixtures/expected/code-table-receipt.special-characters.wpc1252.hex +30 -0
- package/fixtures/expected/code-table-receipt.test-cashregister-sale.iso8859_15.hex +44 -0
- package/fixtures/expected/code-table-receipt.test-cashregister-sale.pc437.hex +44 -0
- package/fixtures/expected/code-table-receipt.test-cashregister-sale.pc850.hex +44 -0
- package/fixtures/expected/code-table-receipt.test-cashregister-sale.pc858.hex +44 -0
- package/fixtures/expected/code-table-receipt.test-cashregister-sale.replacement.hex +44 -0
- package/fixtures/expected/code-table-receipt.test-cashregister-sale.wpc1252.hex +44 -0
- package/fixtures/expected/code-table-test-sheet.lines.json +191 -0
- package/fixtures/expected/code-table-test-sheet.mm58.hex +59 -0
- package/fixtures/expected/code-table-test-sheet.mm80.hex +60 -0
- package/fixtures/hobex-hps-codes.json +1 -1
- package/fixtures/invoice-api.schema.json +1 -1
- package/fixtures/invoice-texts.json +1 -1
- package/fixtures/pos-texts.json +37 -1
- package/fixtures/surface.json +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Katalog der Code-Tabellen fuer Bondrucker und die Umwandlung von Text in
|
|
3
|
+
* Bytes je Tabelle.
|
|
4
|
+
*
|
|
5
|
+
* Warum ein Katalog: `ESC t n` waehlt die Zeichentabelle, aber die Nummer n
|
|
6
|
+
* ist nicht einheitlich. Epson legt WPC1252 auf 16, viele guenstige Drucker
|
|
7
|
+
* nummerieren anders oder kennen die Tabelle gar nicht. Wer am Testblatt
|
|
8
|
+
* sieht, welche Nummer seine Umlaute richtig druckt, waehlt hier die
|
|
9
|
+
* passende Tabelle. Gemeinsamer Prueffall mit dem Dart-Zwilling:
|
|
10
|
+
* `fixtures/code-tables.json`.
|
|
11
|
+
*
|
|
12
|
+
* Jede Tabelle setzt die zehn deutschen Zeichen (Umlaute, ß, €, §, °) auf
|
|
13
|
+
* ein Byte oder, wo die Tabelle das Zeichen nicht hat, auf Ersatzbuchstaben
|
|
14
|
+
* (`€` -> `EUR`). Fuer diese zehn Zeichen kommt nie `?` heraus.
|
|
15
|
+
*/
|
|
16
|
+
/** Die zehn Zeichen, fuer die jede Tabelle eine feste Antwort hat. */
|
|
17
|
+
const ZEHN_ZEICHEN = ['ä', 'ö', 'ü', 'Ä', 'Ö', 'Ü', 'ß', '€', '§', '°'];
|
|
18
|
+
/** Ersatzbuchstaben, wenn die Tabelle das Zeichen nicht hat. */
|
|
19
|
+
const ERSATZ_BUCHSTABEN = {
|
|
20
|
+
'ä': 'ae', 'ö': 'oe', 'ü': 'ue', 'Ä': 'Ae', 'Ö': 'Oe', 'Ü': 'Ue', 'ß': 'ss', '€': 'EUR', '§': 'Par.', '°': 'Grad',
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Byte je Zeichen und Tabelle; fehlt ein Zeichen, gilt der Ersatz. Werte aus
|
|
24
|
+
* den Zeichentabellen (Windows-1252, IBM 858/850/437, ISO 8859-15).
|
|
25
|
+
*/
|
|
26
|
+
const BYTES_JE_TABELLE = {
|
|
27
|
+
wpc1252: { 'ä': 0xe4, 'ö': 0xf6, 'ü': 0xfc, 'Ä': 0xc4, 'Ö': 0xd6, 'Ü': 0xdc, 'ß': 0xdf, '€': 0x80, '§': 0xa7, '°': 0xb0 },
|
|
28
|
+
pc858: { 'ä': 0x84, 'ö': 0x94, 'ü': 0x81, 'Ä': 0x8e, 'Ö': 0x99, 'Ü': 0x9a, 'ß': 0xe1, '€': 0xd5, '§': 0xf5, '°': 0xf8 },
|
|
29
|
+
pc850: { 'ä': 0x84, 'ö': 0x94, 'ü': 0x81, 'Ä': 0x8e, 'Ö': 0x99, 'Ü': 0x9a, 'ß': 0xe1, '§': 0xf5, '°': 0xf8 },
|
|
30
|
+
pc437: { 'ä': 0x84, 'ö': 0x94, 'ü': 0x81, 'Ä': 0x8e, 'Ö': 0x99, 'Ü': 0x9a, 'ß': 0xe1, '°': 0xf8 },
|
|
31
|
+
iso8859_15: { 'ä': 0xe4, 'ö': 0xf6, 'ü': 0xfc, 'Ä': 0xc4, 'Ö': 0xd6, 'Ü': 0xdc, 'ß': 0xdf, '€': 0xa4, '§': 0xa7, '°': 0xb0 },
|
|
32
|
+
replacement: {},
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Ersatzbuchstaben fuer eines der zehn Zeichen (paketintern, fuer
|
|
36
|
+
* `escPosPrintableText` mit gewaehlter Tabelle).
|
|
37
|
+
*/
|
|
38
|
+
export function ersatzBuchstaben(zeichen) {
|
|
39
|
+
const ersatz = ERSATZ_BUCHSTABEN[zeichen];
|
|
40
|
+
if (ersatz === undefined)
|
|
41
|
+
throw new Error(`Kein Ersatz fuer ${zeichen}`);
|
|
42
|
+
return ersatz;
|
|
43
|
+
}
|
|
44
|
+
function tabelle(id, number, escT) {
|
|
45
|
+
const bytes = BYTES_JE_TABELLE[id];
|
|
46
|
+
return Object.freeze({ id, number, escT, missing: Object.freeze(ZEHN_ZEICHEN.filter((z) => bytes[z] === undefined)) });
|
|
47
|
+
}
|
|
48
|
+
/** Alle Code-Tabellen in der Reihenfolge des Testblatts (Nummer 1-6). */
|
|
49
|
+
export const CODE_TABLES = Object.freeze([
|
|
50
|
+
tabelle('wpc1252', 1, 16),
|
|
51
|
+
tabelle('pc858', 2, 19),
|
|
52
|
+
tabelle('pc850', 3, 2),
|
|
53
|
+
tabelle('pc437', 4, 0),
|
|
54
|
+
tabelle('iso8859_15', 5, 40),
|
|
55
|
+
tabelle('replacement', 6, 0),
|
|
56
|
+
]);
|
|
57
|
+
/** Die Tabelle zu einer Kennung; eine unbekannte Kennung wird gemeldet. */
|
|
58
|
+
export function codeTableById(id) {
|
|
59
|
+
const gefunden = CODE_TABLES.find((t) => t.id === id);
|
|
60
|
+
if (gefunden === undefined)
|
|
61
|
+
throw new Error(`Unbekannte Code-Tabelle: ${String(id)}`);
|
|
62
|
+
return gefunden;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Tabelle aus der gespeicherten Einstellung (`cp1252`/`cp437`). Alles andere,
|
|
66
|
+
* auch keine Einstellung, ist die Vorgabe `wpc1252`.
|
|
67
|
+
*/
|
|
68
|
+
export function codeTableFromSetting(setting) {
|
|
69
|
+
return setting === 'cp437' ? 'pc437' : 'wpc1252';
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Zeichen, die das Vorbild vor dem Kodieren ersetzt (generator.dart `_encode`).
|
|
73
|
+
*
|
|
74
|
+
* **Eine bewusste Abweichung:** Fuer `•` sagt generator.dart `.`,
|
|
75
|
+
* print_paper.dart (portiert als `escPosPrintableText`) dagegen `*`. In Darts
|
|
76
|
+
* eigener Kette faellt das nie auf, weil print_paper vor dem Erzeuger ersetzt
|
|
77
|
+
* und der Erzeuger den Punkt nie zu sehen bekommt -- die gedruckte Antwort ist
|
|
78
|
+
* dort also `*`. Ein Verbraucher dieses Pakets kann `escPosText` aber auch
|
|
79
|
+
* direkt aufrufen, und dann duerfen nicht zwei Zeichen fuer dasselbe Zeichen
|
|
80
|
+
* herauskommen. Deshalb gilt hier dieselbe Antwort wie dort.
|
|
81
|
+
*/
|
|
82
|
+
export const ZEICHEN_ERSATZ = [
|
|
83
|
+
['’', "'"], // typografisches Apostroph
|
|
84
|
+
['´', "'"], // Akut
|
|
85
|
+
['•', '*'], // Aufzaehlungspunkt (siehe Kommentar oben)
|
|
86
|
+
];
|
|
87
|
+
/**
|
|
88
|
+
* Latin-1-Byte -> CP437-Byte fuer die Zeichen, die CP437 kennt (deutsche
|
|
89
|
+
* Umlaute, ß, westeuropaeische Akzente, Waehrungs-/Sonderzeichen). Alles
|
|
90
|
+
* andere ab 0x80 hat in CP437 keinen Platz und wird zu "?".
|
|
91
|
+
*/
|
|
92
|
+
export const CP437_AUS_LATIN1 = new Map([
|
|
93
|
+
[0xc7, 0x80], [0xfc, 0x81], [0xe9, 0x82], [0xe2, 0x83], [0xe4, 0x84], [0xe0, 0x85], [0xe5, 0x86], [0xe7, 0x87],
|
|
94
|
+
[0xea, 0x88], [0xeb, 0x89], [0xe8, 0x8a], [0xef, 0x8b], [0xee, 0x8c], [0xec, 0x8d], [0xc4, 0x8e], [0xc5, 0x8f],
|
|
95
|
+
[0xc9, 0x90], [0xe6, 0x91], [0xc6, 0x92], [0xf4, 0x93], [0xf6, 0x94], [0xf2, 0x95], [0xfb, 0x96], [0xf9, 0x97],
|
|
96
|
+
[0xff, 0x98], [0xd6, 0x99], [0xdc, 0x9a], [0xa2, 0x9b], [0xa3, 0x9c], [0xa5, 0x9d], [0xe1, 0xa0], [0xed, 0xa1],
|
|
97
|
+
[0xf3, 0xa2], [0xfa, 0xa3], [0xf1, 0xa4], [0xd1, 0xa5], [0xaa, 0xa6], [0xba, 0xa7], [0xbf, 0xa8], [0xac, 0xaa],
|
|
98
|
+
[0xbd, 0xab], [0xbc, 0xac], [0xa1, 0xad], [0xab, 0xae], [0xbb, 0xaf], [0xdf, 0xe1], [0xb5, 0xe6], [0xb1, 0xf1],
|
|
99
|
+
[0xf7, 0xf6], [0xb0, 0xf8], [0xb7, 0xfa], [0xb2, 0xfd], [0xa0, 0xff],
|
|
100
|
+
]);
|
|
101
|
+
/**
|
|
102
|
+
* Latin-1-Byte -> PC850-Byte (IBM 850, gleich fuer 858 bis auf das €, das
|
|
103
|
+
* die zehn Zeichen oben schon setzen). PC850 hat fuer jedes Latin-1-Zeichen
|
|
104
|
+
* ab 0xA0 einen Platz; die Steuerzeichen 0x80-0x9F werden zu "?".
|
|
105
|
+
*/
|
|
106
|
+
const PC850_AUS_LATIN1 = new Map([
|
|
107
|
+
[0xa0, 0xff], [0xa1, 0xad], [0xa2, 0xbd], [0xa3, 0x9c], [0xa4, 0xcf], [0xa5, 0xbe], [0xa6, 0xdd], [0xa7, 0xf5],
|
|
108
|
+
[0xa8, 0xf9], [0xa9, 0xb8], [0xaa, 0xa6], [0xab, 0xae], [0xac, 0xaa], [0xad, 0xf0], [0xae, 0xa9], [0xaf, 0xee],
|
|
109
|
+
[0xb0, 0xf8], [0xb1, 0xf1], [0xb2, 0xfd], [0xb3, 0xfc], [0xb4, 0xef], [0xb5, 0xe6], [0xb6, 0xf4], [0xb7, 0xfa],
|
|
110
|
+
[0xb8, 0xf7], [0xb9, 0xfb], [0xba, 0xa7], [0xbb, 0xaf], [0xbc, 0xac], [0xbd, 0xab], [0xbe, 0xf3], [0xbf, 0xa8],
|
|
111
|
+
[0xc0, 0xb7], [0xc1, 0xb5], [0xc2, 0xb6], [0xc3, 0xc7], [0xc4, 0x8e], [0xc5, 0x8f], [0xc6, 0x92], [0xc7, 0x80],
|
|
112
|
+
[0xc8, 0xd4], [0xc9, 0x90], [0xca, 0xd2], [0xcb, 0xd3], [0xcc, 0xde], [0xcd, 0xd6], [0xce, 0xd7], [0xcf, 0xd8],
|
|
113
|
+
[0xd0, 0xd1], [0xd1, 0xa5], [0xd2, 0xe3], [0xd3, 0xe0], [0xd4, 0xe2], [0xd5, 0xe5], [0xd6, 0x99], [0xd7, 0x9e],
|
|
114
|
+
[0xd8, 0x9d], [0xd9, 0xeb], [0xda, 0xe9], [0xdb, 0xea], [0xdc, 0x9a], [0xdd, 0xed], [0xde, 0xe8], [0xdf, 0xe1],
|
|
115
|
+
[0xe0, 0x85], [0xe1, 0xa0], [0xe2, 0x83], [0xe3, 0xc6], [0xe4, 0x84], [0xe5, 0x86], [0xe6, 0x91], [0xe7, 0x87],
|
|
116
|
+
[0xe8, 0x8a], [0xe9, 0x82], [0xea, 0x88], [0xeb, 0x89], [0xec, 0x8d], [0xed, 0xa1], [0xee, 0x8c], [0xef, 0x8b],
|
|
117
|
+
[0xf0, 0xd0], [0xf1, 0xa4], [0xf2, 0x95], [0xf3, 0xa2], [0xf4, 0x93], [0xf5, 0xe4], [0xf6, 0x94], [0xf7, 0xf6],
|
|
118
|
+
[0xf8, 0x9b], [0xf9, 0x97], [0xfa, 0xa3], [0xfb, 0x96], [0xfc, 0x81], [0xfd, 0xec], [0xfe, 0xe7], [0xff, 0x98],
|
|
119
|
+
]);
|
|
120
|
+
const FRAGEZEICHEN = 0x3f;
|
|
121
|
+
/**
|
|
122
|
+
* Windows-1252 belegt 0x80-0x9F mit eigenen Zeichen (Latin-1 hat dort nur
|
|
123
|
+
* Steuerzeichen). € setzen die zehn Zeichen, ’ und • ersetzt ZEICHEN_ERSATZ
|
|
124
|
+
* vorher (eine Antwort auf jedem Ausgabeweg); der Rest steht hier.
|
|
125
|
+
*/
|
|
126
|
+
const WPC1252_NEU = new Map([
|
|
127
|
+
[0x201a, 0x82], [0x0192, 0x83], [0x201e, 0x84], [0x2026, 0x85], [0x2020, 0x86], [0x2021, 0x87], [0x02c6, 0x88],
|
|
128
|
+
[0x2030, 0x89], [0x0160, 0x8a], [0x2039, 0x8b], [0x0152, 0x8c], [0x017d, 0x8e], [0x2018, 0x91], [0x2019, 0x92],
|
|
129
|
+
[0x201c, 0x93], [0x201d, 0x94], [0x2022, 0x95], [0x2013, 0x96], [0x2014, 0x97], [0x02dc, 0x98], [0x2122, 0x99],
|
|
130
|
+
[0x0161, 0x9a], [0x203a, 0x9b], [0x0153, 0x9c], [0x017e, 0x9e], [0x0178, 0x9f],
|
|
131
|
+
]);
|
|
132
|
+
/**
|
|
133
|
+
* ISO 8859-15 belegt acht Stellen anders als Latin-1: dort stehen € Š š Ž ž
|
|
134
|
+
* Œ œ Ÿ statt ¤ ¦ ¨ ´ ¸ ¼ ½ ¾. Die acht Latin-1-Zeichen fehlen der Tabelle
|
|
135
|
+
* (Ersetzung, sonst `?`), die neuen stehen hier mit ihrem Byte (€ setzen
|
|
136
|
+
* schon die zehn Zeichen). C1-Steuerzeichen (0x80-0x9F) gehen nie roh hinaus.
|
|
137
|
+
*/
|
|
138
|
+
const ISO8859_15_ANDERS = new Set([0xa4, 0xa6, 0xa8, 0xb4, 0xb8, 0xbc, 0xbd, 0xbe]);
|
|
139
|
+
const ISO8859_15_NEU = new Map([
|
|
140
|
+
[0x0160, 0xa6], [0x0161, 0xa8], [0x017d, 0xb4], [0x017e, 0xb8], [0x0152, 0xbc], [0x0153, 0xbd], [0x0178, 0xbe],
|
|
141
|
+
]);
|
|
142
|
+
/** Byte fuer ein Zeichen ab 0x80, das nicht zu den zehn gehoert. */
|
|
143
|
+
function uebrigesZeichen(codepunkt, id) {
|
|
144
|
+
switch (id) {
|
|
145
|
+
case 'wpc1252':
|
|
146
|
+
if (codepunkt < 0xa0)
|
|
147
|
+
return FRAGEZEICHEN; // C1-Steuerzeichen
|
|
148
|
+
if (codepunkt <= 0xff)
|
|
149
|
+
return codepunkt;
|
|
150
|
+
return WPC1252_NEU.get(codepunkt) ?? FRAGEZEICHEN;
|
|
151
|
+
case 'iso8859_15':
|
|
152
|
+
if (codepunkt < 0xa0)
|
|
153
|
+
return FRAGEZEICHEN; // C1-Steuerzeichen
|
|
154
|
+
if (codepunkt <= 0xff)
|
|
155
|
+
return ISO8859_15_ANDERS.has(codepunkt) ? FRAGEZEICHEN : codepunkt;
|
|
156
|
+
return ISO8859_15_NEU.get(codepunkt) ?? FRAGEZEICHEN;
|
|
157
|
+
case 'pc437':
|
|
158
|
+
return CP437_AUS_LATIN1.get(codepunkt) ?? FRAGEZEICHEN;
|
|
159
|
+
case 'pc858':
|
|
160
|
+
case 'pc850':
|
|
161
|
+
return PC850_AUS_LATIN1.get(codepunkt) ?? FRAGEZEICHEN;
|
|
162
|
+
case 'replacement':
|
|
163
|
+
return FRAGEZEICHEN;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Wandelt Text in die Bytes einer Code-Tabelle: erst die vorhandenen
|
|
168
|
+
* Ersetzungen (`ZEICHEN_ERSATZ`), dann die zehn deutschen Zeichen je Tabelle
|
|
169
|
+
* (Byte oder Ersatzbuchstaben), ASCII unveraendert, alles uebrige ueber die
|
|
170
|
+
* Abbildung der Tabelle, sonst `?`. Ein Zeichen, das die Tabelle nicht
|
|
171
|
+
* kennt, ist genau ein Byte; nur die Ersatzbuchstaben machen aus einem
|
|
172
|
+
* Zeichen mehrere. Spalten darum immer an den fertigen Bytes messen.
|
|
173
|
+
*/
|
|
174
|
+
export function encodeForCodeTable(text, table) {
|
|
175
|
+
return encodeReplaced(replaceKnownCharacters(text), table);
|
|
176
|
+
}
|
|
177
|
+
/** Wendet `ZEICHEN_ERSATZ` an (paketintern, nicht exportiert ueber den Einstieg). */
|
|
178
|
+
export function replaceKnownCharacters(text) {
|
|
179
|
+
let aufbereitet = text;
|
|
180
|
+
for (const [von, nach] of ZEICHEN_ERSATZ) {
|
|
181
|
+
aufbereitet = aufbereitet.split(von).join(nach);
|
|
182
|
+
}
|
|
183
|
+
return aufbereitet;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Wie `encodeForCodeTable`, aber fuer Text, der `ZEICHEN_ERSATZ` schon hinter
|
|
187
|
+
* sich hat (paketintern: der alte Pfad in `encodeEscPosText` ersetzt vor der
|
|
188
|
+
* Latin-1-Pruefung und soll nicht zweimal ersetzen).
|
|
189
|
+
*/
|
|
190
|
+
export function encodeReplaced(aufbereitet, table) {
|
|
191
|
+
const bytesDerTabelle = BYTES_JE_TABELLE[table];
|
|
192
|
+
if (bytesDerTabelle === undefined)
|
|
193
|
+
throw new Error(`Unbekannte Code-Tabelle: ${String(table)}`);
|
|
194
|
+
const bytes = [];
|
|
195
|
+
for (const zeichen of aufbereitet) {
|
|
196
|
+
const codepunkt = zeichen.codePointAt(0);
|
|
197
|
+
if (codepunkt < 0x80) {
|
|
198
|
+
bytes.push(codepunkt);
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
const byte = bytesDerTabelle[zeichen];
|
|
202
|
+
if (byte !== undefined) {
|
|
203
|
+
bytes.push(byte);
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
const ersatz = ERSATZ_BUCHSTABEN[zeichen];
|
|
207
|
+
if (ersatz !== undefined) {
|
|
208
|
+
for (let i = 0; i < ersatz.length; i++)
|
|
209
|
+
bytes.push(ersatz.charCodeAt(i));
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
bytes.push(uebrigesZeichen(codepunkt, table));
|
|
213
|
+
}
|
|
214
|
+
return Uint8Array.from(bytes);
|
|
215
|
+
}
|
|
@@ -23,11 +23,14 @@
|
|
|
23
23
|
* `ESC t 16` und bleiben in CP437; dann werden die Umlaute auf ihre
|
|
24
24
|
* CP437-Plaetze umkodiert (ä = 0x84, ü = 0x81, ß = 0xE1, ...). Zeichen ohne
|
|
25
25
|
* CP437-Platz werden zu `?` — weiterhin ein Byte je Zeichen.
|
|
26
|
+
* Weitere Tabellen (PC858, PC850, ISO 8859-15, reine Ersatzbuchstaben) und
|
|
27
|
+
* ihre `ESC t`-Nummern stehen im Katalog `code-tables.ts`.
|
|
26
28
|
*
|
|
27
29
|
* Nicht enthalten (bewusst): Bilddekodierung (PNG/JPEG liest die Huelle),
|
|
28
30
|
* Capability-Profile einzelner Druckermodelle, Kassenlade, 1D-Barcodes.
|
|
29
31
|
* Fertige einfarbige Rasterbilder (Logo) gehen ueber [escPosRasterImage].
|
|
30
32
|
*/
|
|
33
|
+
import { type CodeTableId } from './code-tables.js';
|
|
31
34
|
import { type QrModuleSize } from './qr-groesse.js';
|
|
32
35
|
/** Papierbreite der Bonrolle. */
|
|
33
36
|
export type PosPaperSize = 'mm58' | 'mm80';
|
|
@@ -37,8 +40,12 @@ export type PosAlign = 'left' | 'center' | 'right';
|
|
|
37
40
|
export type PosFont = 'fontA' | 'fontB';
|
|
38
41
|
/** Voller oder teilweiser Papierschnitt. */
|
|
39
42
|
export type PosCutMode = 'full' | 'partial';
|
|
40
|
-
/**
|
|
41
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Vom Drucker zu verwendende Codepage: eine Tabelle des Katalogs
|
|
45
|
+
* (`CODE_TABLES`) oder einer der alten Namen. `CP1252` entspricht `wpc1252`,
|
|
46
|
+
* `CP437` entspricht `pc437`.
|
|
47
|
+
*/
|
|
48
|
+
export type PosCodeTable = 'CP437' | 'CP1252' | CodeTableId;
|
|
42
49
|
/** Zeichenvergroesserung (1 = einfach, 2 = doppelt, ... bis 8). */
|
|
43
50
|
export type PosTextSize = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
|
|
44
51
|
/** Modulgroesse des QR-Codes (Punkte je Modul). */
|
|
@@ -171,10 +178,16 @@ export interface EscPosDocument {
|
|
|
171
178
|
styles: AktuelleStile;
|
|
172
179
|
}
|
|
173
180
|
/**
|
|
174
|
-
* Kodiert Text so, wie ihn der Drucker erwartet: ein Byte je Zeichen
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
181
|
+
* Kodiert Text so, wie ihn der Drucker erwartet: ein Byte je Zeichen in der
|
|
182
|
+
* gewaehlten Tabelle (`encodeForCodeTable`). Ein Umlaut wird damit zu genau
|
|
183
|
+
* einem Byte -- Voraussetzung dafuer, dass die Spaltenrechnung stimmt.
|
|
184
|
+
*
|
|
185
|
+
* Die alten Namen `CP1252` und `CP437` bleiben streng: ein Zeichen ausserhalb
|
|
186
|
+
* Latin-1 wird gemeldet statt verstuemmelt (vorher `escPosPrintableText`
|
|
187
|
+
* anwenden). `CP1252` gibt Latin-1 byte-gleich wie bisher aus (auch ein
|
|
188
|
+
* C1-Steuerzeichen roh, das `wpc1252` zu `?` macht); `CP437` hat die Bytes
|
|
189
|
+
* von `pc437`. Die Tabellen des Katalogs wandeln dagegen jedes Zeichen um
|
|
190
|
+
* (Ersatzbuchstaben, sonst `?`).
|
|
178
191
|
*/
|
|
179
192
|
export declare function encodeEscPosText(text: string, codeTable?: PosCodeTable): Uint8Array;
|
|
180
193
|
/** Zeichen je Zeile fuer Papier und Schrift (`fontA`, wenn nichts gesetzt ist). */
|
|
@@ -23,11 +23,14 @@
|
|
|
23
23
|
* `ESC t 16` und bleiben in CP437; dann werden die Umlaute auf ihre
|
|
24
24
|
* CP437-Plaetze umkodiert (ä = 0x84, ü = 0x81, ß = 0xE1, ...). Zeichen ohne
|
|
25
25
|
* CP437-Platz werden zu `?` — weiterhin ein Byte je Zeichen.
|
|
26
|
+
* Weitere Tabellen (PC858, PC850, ISO 8859-15, reine Ersatzbuchstaben) und
|
|
27
|
+
* ihre `ESC t`-Nummern stehen im Katalog `code-tables.ts`.
|
|
26
28
|
*
|
|
27
29
|
* Nicht enthalten (bewusst): Bilddekodierung (PNG/JPEG liest die Huelle),
|
|
28
30
|
* Capability-Profile einzelner Druckermodelle, Kassenlade, 1D-Barcodes.
|
|
29
31
|
* Fertige einfarbige Rasterbilder (Logo) gehen ueber [escPosRasterImage].
|
|
30
32
|
*/
|
|
33
|
+
import { CODE_TABLES, encodeForCodeTable, encodeReplaced, replaceKnownCharacters, } from './code-tables.js';
|
|
31
34
|
import { QR_PRINT_WIDTH_DOTS, QR_MIN_MODULE_DOTS, QR_MODULE_SIZE_CAP, QR_QUIET_ZONE_MODULES, qrSizingFor, } from './qr-groesse.js';
|
|
32
35
|
// -------------------------------------------------------------- Befehlsbytes
|
|
33
36
|
// Wortwoertlich aus commands.dart. Die Zahlen sind ASCII-Codes der dortigen
|
|
@@ -61,8 +64,15 @@ const C_POS = [ESC, 0x24]; // ESC $ nL nH
|
|
|
61
64
|
const C_FEED_N = [ESC, 0x64]; // ESC d n
|
|
62
65
|
const C_QR_HEADER = [GS, 0x28, 0x6b]; // GS ( k
|
|
63
66
|
const ZEILENUMBRUCH = 0x0a;
|
|
64
|
-
/**
|
|
65
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Codepage-Nummern fuer `ESC t n`: die alten Namen aus capability_profile.dart
|
|
69
|
+
* (CP437 = 0, CP1252 = 16), dazu jede Tabelle des Katalogs.
|
|
70
|
+
*/
|
|
71
|
+
const CODEPAGE_ID = {
|
|
72
|
+
CP437: 0,
|
|
73
|
+
CP1252: 16,
|
|
74
|
+
...Object.fromEntries(CODE_TABLES.map((t) => [t.id, t.escT])),
|
|
75
|
+
};
|
|
66
76
|
/** Korrekturstufen fuer GS ( k Funktion 169 — aus qrcode.dart. */
|
|
67
77
|
const QR_KORREKTUR = { L: 48, M: 49, Q: 50, H: 51 };
|
|
68
78
|
/** Nennbreite der Rolle in Millimetern — nur fuer Meldungstexte. */
|
|
@@ -82,22 +92,6 @@ const ZEICHEN_JE_ZEILE = {
|
|
|
82
92
|
mm58: { fontA: 32, fontB: 42 },
|
|
83
93
|
mm80: { fontA: 48, fontB: 64 },
|
|
84
94
|
};
|
|
85
|
-
/**
|
|
86
|
-
* Zeichen, die das Vorbild vor dem Kodieren ersetzt (generator.dart `_encode`).
|
|
87
|
-
*
|
|
88
|
-
* **Eine bewusste Abweichung:** Fuer `•` sagt generator.dart `.`,
|
|
89
|
-
* print_paper.dart (portiert als `escPosPrintableText`) dagegen `*`. In Darts
|
|
90
|
-
* eigener Kette faellt das nie auf, weil print_paper vor dem Erzeuger ersetzt
|
|
91
|
-
* und der Erzeuger den Punkt nie zu sehen bekommt — die gedruckte Antwort ist
|
|
92
|
-
* dort also `*`. Ein Verbraucher dieses Pakets kann `escPosText` aber auch
|
|
93
|
-
* direkt aufrufen, und dann duerfen nicht zwei Zeichen fuer dasselbe Zeichen
|
|
94
|
-
* herauskommen. Deshalb gilt hier dieselbe Antwort wie dort.
|
|
95
|
-
*/
|
|
96
|
-
const ZEICHEN_ERSATZ = [
|
|
97
|
-
['’', "'"], // typografisches Apostroph
|
|
98
|
-
['´', "'"], // Akut
|
|
99
|
-
['•', '*'], // Aufzaehlungspunkt (siehe Kommentar oben)
|
|
100
|
-
];
|
|
101
95
|
// ------------------------------------------------------------------ Helfer
|
|
102
96
|
function anhaengen(doc, bytes) {
|
|
103
97
|
const ziel = doc.bytes;
|
|
@@ -128,40 +122,25 @@ function latin1(text) {
|
|
|
128
122
|
return bytes;
|
|
129
123
|
}
|
|
130
124
|
/**
|
|
131
|
-
* Kodiert Text so, wie ihn der Drucker erwartet: ein Byte je Zeichen
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
125
|
+
* Kodiert Text so, wie ihn der Drucker erwartet: ein Byte je Zeichen in der
|
|
126
|
+
* gewaehlten Tabelle (`encodeForCodeTable`). Ein Umlaut wird damit zu genau
|
|
127
|
+
* einem Byte -- Voraussetzung dafuer, dass die Spaltenrechnung stimmt.
|
|
128
|
+
*
|
|
129
|
+
* Die alten Namen `CP1252` und `CP437` bleiben streng: ein Zeichen ausserhalb
|
|
130
|
+
* Latin-1 wird gemeldet statt verstuemmelt (vorher `escPosPrintableText`
|
|
131
|
+
* anwenden). `CP1252` gibt Latin-1 byte-gleich wie bisher aus (auch ein
|
|
132
|
+
* C1-Steuerzeichen roh, das `wpc1252` zu `?` macht); `CP437` hat die Bytes
|
|
133
|
+
* von `pc437`. Die Tabellen des Katalogs wandeln dagegen jedes Zeichen um
|
|
134
|
+
* (Ersatzbuchstaben, sonst `?`).
|
|
135
135
|
*/
|
|
136
136
|
export function encodeEscPosText(text, codeTable = 'CP1252') {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const bytes = latin1(aufbereitet);
|
|
142
|
-
if (codeTable !== 'CP437')
|
|
143
|
-
return bytes;
|
|
144
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
145
|
-
const b = bytes[i] ?? 0;
|
|
146
|
-
if (b >= 0x80)
|
|
147
|
-
bytes[i] = CP437_AUS_LATIN1.get(b) ?? 0x3f;
|
|
137
|
+
if (codeTable === 'CP1252' || codeTable === 'CP437') {
|
|
138
|
+
const aufbereitet = replaceKnownCharacters(text);
|
|
139
|
+
const bytes = latin1(aufbereitet); // wirft ausserhalb Latin-1
|
|
140
|
+
return codeTable === 'CP1252' ? bytes : encodeReplaced(aufbereitet, 'pc437');
|
|
148
141
|
}
|
|
149
|
-
return
|
|
142
|
+
return encodeForCodeTable(text, codeTable);
|
|
150
143
|
}
|
|
151
|
-
/**
|
|
152
|
-
* Latin-1-Byte -> CP437-Byte fuer die Zeichen, die CP437 kennt (deutsche
|
|
153
|
-
* Umlaute, ß, westeuropaeische Akzente, Waehrungs-/Sonderzeichen). Alles
|
|
154
|
-
* andere ab 0x80 hat in CP437 keinen Platz und wird zu "?".
|
|
155
|
-
*/
|
|
156
|
-
const CP437_AUS_LATIN1 = new Map([
|
|
157
|
-
[0xc7, 0x80], [0xfc, 0x81], [0xe9, 0x82], [0xe2, 0x83], [0xe4, 0x84], [0xe0, 0x85], [0xe5, 0x86], [0xe7, 0x87],
|
|
158
|
-
[0xea, 0x88], [0xeb, 0x89], [0xe8, 0x8a], [0xef, 0x8b], [0xee, 0x8c], [0xec, 0x8d], [0xc4, 0x8e], [0xc5, 0x8f],
|
|
159
|
-
[0xc9, 0x90], [0xe6, 0x91], [0xc6, 0x92], [0xf4, 0x93], [0xf6, 0x94], [0xf2, 0x95], [0xfb, 0x96], [0xf9, 0x97],
|
|
160
|
-
[0xff, 0x98], [0xd6, 0x99], [0xdc, 0x9a], [0xa2, 0x9b], [0xa3, 0x9c], [0xa5, 0x9d], [0xe1, 0xa0], [0xed, 0xa1],
|
|
161
|
-
[0xf3, 0xa2], [0xfa, 0xa3], [0xf1, 0xa4], [0xd1, 0xa5], [0xaa, 0xa6], [0xba, 0xa7], [0xbf, 0xa8], [0xac, 0xaa],
|
|
162
|
-
[0xbd, 0xab], [0xbc, 0xac], [0xa1, 0xad], [0xab, 0xae], [0xbb, 0xaf], [0xdf, 0xe1], [0xb5, 0xe6], [0xb1, 0xf1],
|
|
163
|
-
[0xf7, 0xf6], [0xb0, 0xf8], [0xb7, 0xfa], [0xb2, 0xfd], [0xa0, 0xff],
|
|
164
|
-
]);
|
|
165
144
|
/** Zeichen je Zeile fuer Papier und Schrift (`fontA`, wenn nichts gesetzt ist). */
|
|
166
145
|
export function escPosMaxCharsPerLine(paperSize, font) {
|
|
167
146
|
const breiten = ZEICHEN_JE_ZEILE[paperSize];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
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, qrRasterDots, type RasterImage, rasterRowsBytes, rasterRowsBase64, escPosRasterImage, encodeEscPosText, qrCodeBytes, escPosMaxCharsPerLine, escPosWrapLines, wrapText, } from './escpos.js';
|
|
2
|
+
export { type CodeTableId, type CodeTable, CODE_TABLES, codeTableById, codeTableFromSetting, encodeForCodeTable, } from './code-tables.js';
|
|
2
3
|
export { type QrModuleSize, type QrSizing, QR_MODULE_SIZE_CAP, QR_QUIET_ZONE_MODULES, QR_MIN_MODULE_DOTS, QR_EXCEPTION_MODULE_DOTS, QR_MAX_MODULE_DOTS, QR_PRINT_WIDTH_DOTS, qrModuleCount, qrFitsInVersion, computeQrSizing, qrSizingFor, } from './qr-groesse.js';
|
|
3
4
|
export { escPosPrintableText } from './printable.js';
|
|
4
5
|
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,4 +1,5 @@
|
|
|
1
1
|
export { createEscPosDocument, escPosBytes, escPosReset, escPosSetGlobalCodeTable, escPosSetGlobalFont, escPosSetStyles, escPosText, escPosEmptyLines, escPosFeed, escPosCut, escPosHr, escPosRow, escPosQrCode, escPosQrRaster, qrRasterDots, rasterRowsBytes, rasterRowsBase64, escPosRasterImage, encodeEscPosText, qrCodeBytes, escPosMaxCharsPerLine, escPosWrapLines, wrapText, } from './escpos.js';
|
|
2
|
+
export { CODE_TABLES, codeTableById, codeTableFromSetting, encodeForCodeTable, } from './code-tables.js';
|
|
2
3
|
export { QR_MODULE_SIZE_CAP, QR_QUIET_ZONE_MODULES, QR_MIN_MODULE_DOTS, QR_EXCEPTION_MODULE_DOTS, QR_MAX_MODULE_DOTS, QR_PRINT_WIDTH_DOTS, qrModuleCount, qrFitsInVersion, computeQrSizing, qrSizingFor, } from './qr-groesse.js';
|
|
3
4
|
export { escPosPrintableText } from './printable.js';
|
|
4
5
|
export { USB_VENDOR_EPSON, USB_CLASS_PRINTER, UsbTimeoutError, usbDeviceKey, usbFindPrinterEndpoint, usbWriteAll, usbConnectPrinter, usbPrint, usbDisconnect, } from './webusb.js';
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* ersatzlos weg, alles Uebrige auf `?`. Ein Artikelname aus einer
|
|
16
16
|
* ERP-Uebernahme mit Gedankenstrich soll den Beleg nicht verhindern.
|
|
17
17
|
*/
|
|
18
|
+
import type { PosCodeTable } from './escpos.js';
|
|
18
19
|
/**
|
|
19
20
|
* Ersetzt alles, was der Bondrucker nicht darstellen kann, durch eine
|
|
20
21
|
* druckbare Entsprechung. Reine Funktion, ohne Zustand und ohne Drucker.
|
|
@@ -22,6 +23,17 @@
|
|
|
22
23
|
* Vor `escPosText`/`escPosRow` anwenden, wenn der Text aus fremder Hand kommt
|
|
23
24
|
* (Artikelstamm, ERP-Uebernahme, Kundenname). `•` wird hier zu `*`, und der
|
|
24
25
|
* Erzeuger sagt dasselbe — auch wer diese Funktion weglaesst, bekommt also
|
|
25
|
-
* dasselbe Zeichen (siehe ZEICHEN_ERSATZ in
|
|
26
|
+
* dasselbe Zeichen (siehe ZEICHEN_ERSATZ in code-tables.ts).
|
|
27
|
+
*
|
|
28
|
+
* Mit `codeTable` wird der Text fuer genau diese Tabelle fertig gemacht:
|
|
29
|
+
* - eine Tabelle des Katalogs (`CodeTableId`): `€` bleibt stehen, wenn die
|
|
30
|
+
* Tabelle es hat (der Drucker bekommt das echte Byte), sonst `EUR`; jedes
|
|
31
|
+
* der zehn Zeichen, das der Tabelle fehlt (`§` auf pc437, alle Umlaute auf
|
|
32
|
+
* `replacement` ...), wird schon hier zu seinen Ersatzbuchstaben. Danach
|
|
33
|
+
* ist jedes Zeichen genau ein Byte, und Spalten, die am Text gerechnet
|
|
34
|
+
* werden, stimmen auch am Papier.
|
|
35
|
+
* - `CP437` (alter Name): wie `pc437`, also `§` -> `Par.`.
|
|
36
|
+
* - ohne Angabe, `null` oder `CP1252`: genau wie bisher (Bons ohne gewaehlte
|
|
37
|
+
* Tabelle bleiben byte-gleich).
|
|
26
38
|
*/
|
|
27
|
-
export declare function escPosPrintableText(text: string): string;
|
|
39
|
+
export declare function escPosPrintableText(text: string, codeTable?: PosCodeTable | null): string;
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* ersatzlos weg, alles Uebrige auf `?`. Ein Artikelname aus einer
|
|
16
16
|
* ERP-Uebernahme mit Gedankenstrich soll den Beleg nicht verhindern.
|
|
17
17
|
*/
|
|
18
|
+
import { codeTableById, ersatzBuchstaben } from './code-tables.js';
|
|
18
19
|
/** Ersetzungen aus print_paper.dart, Schluessel sind Unicode-Codepunkte. */
|
|
19
20
|
const ERSETZUNGEN = new Map([
|
|
20
21
|
[0x2013, '-'], // – Halbgeviertstrich
|
|
@@ -63,12 +64,34 @@ function istEmojiOderNullbreite(codepunkt) {
|
|
|
63
64
|
* Vor `escPosText`/`escPosRow` anwenden, wenn der Text aus fremder Hand kommt
|
|
64
65
|
* (Artikelstamm, ERP-Uebernahme, Kundenname). `•` wird hier zu `*`, und der
|
|
65
66
|
* Erzeuger sagt dasselbe — auch wer diese Funktion weglaesst, bekommt also
|
|
66
|
-
* dasselbe Zeichen (siehe ZEICHEN_ERSATZ in
|
|
67
|
+
* dasselbe Zeichen (siehe ZEICHEN_ERSATZ in code-tables.ts).
|
|
68
|
+
*
|
|
69
|
+
* Mit `codeTable` wird der Text fuer genau diese Tabelle fertig gemacht:
|
|
70
|
+
* - eine Tabelle des Katalogs (`CodeTableId`): `€` bleibt stehen, wenn die
|
|
71
|
+
* Tabelle es hat (der Drucker bekommt das echte Byte), sonst `EUR`; jedes
|
|
72
|
+
* der zehn Zeichen, das der Tabelle fehlt (`§` auf pc437, alle Umlaute auf
|
|
73
|
+
* `replacement` ...), wird schon hier zu seinen Ersatzbuchstaben. Danach
|
|
74
|
+
* ist jedes Zeichen genau ein Byte, und Spalten, die am Text gerechnet
|
|
75
|
+
* werden, stimmen auch am Papier.
|
|
76
|
+
* - `CP437` (alter Name): wie `pc437`, also `§` -> `Par.`.
|
|
77
|
+
* - ohne Angabe, `null` oder `CP1252`: genau wie bisher (Bons ohne gewaehlte
|
|
78
|
+
* Tabelle bleiben byte-gleich).
|
|
67
79
|
*/
|
|
68
|
-
export function escPosPrintableText(text) {
|
|
80
|
+
export function escPosPrintableText(text, codeTable) {
|
|
81
|
+
const tabelle = tabelleFuerErsatz(codeTable);
|
|
82
|
+
const fehlend = tabelle === null ? [] : codeTableById(tabelle).missing;
|
|
83
|
+
const echtesEuro = tabelle !== null && !fehlend.includes('€');
|
|
69
84
|
let ergebnis = '';
|
|
70
85
|
for (const zeichen of text) {
|
|
71
86
|
const codepunkt = zeichen.codePointAt(0);
|
|
87
|
+
if (fehlend.includes(zeichen)) {
|
|
88
|
+
ergebnis += ersatzBuchstaben(zeichen);
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (codepunkt === 0x20ac && echtesEuro) {
|
|
92
|
+
ergebnis += zeichen;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
72
95
|
const ersatz = ERSETZUNGEN.get(codepunkt);
|
|
73
96
|
if (ersatz !== undefined) {
|
|
74
97
|
ergebnis += ersatz;
|
|
@@ -85,3 +108,14 @@ export function escPosPrintableText(text) {
|
|
|
85
108
|
}
|
|
86
109
|
return ergebnis;
|
|
87
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Tabelle, deren fehlende Zeichen schon am Text ersetzt werden. `null` heisst
|
|
113
|
+
* alter Weg ohne Aenderung (keine Wahl, `null`, `CP1252`).
|
|
114
|
+
*/
|
|
115
|
+
function tabelleFuerErsatz(codeTable) {
|
|
116
|
+
if (codeTable === undefined || codeTable === null || codeTable === 'CP1252')
|
|
117
|
+
return null;
|
|
118
|
+
if (codeTable === 'CP437')
|
|
119
|
+
return 'pc437';
|
|
120
|
+
return codeTable;
|
|
121
|
+
}
|
package/dist/esm/react/index.js
CHANGED
|
@@ -90,6 +90,13 @@ export function ReceiptSheetLines({ sheet: blatt, logoUrl, renderQr, qrHidden: q
|
|
|
90
90
|
return (_jsx("div", { className: klasse, "data-zeichen": z, style: blattStil, children: blatt.blocks.map((b, i) => {
|
|
91
91
|
switch (b.kind) {
|
|
92
92
|
case 'line':
|
|
93
|
+
if (b.doubleSizeLead !== undefined && b.doubleSizeLead > 0) {
|
|
94
|
+
// Wie am Papier (`GS !` doppelt): die Nummernzelle in doppelter
|
|
95
|
+
// Schrift, die Zeile zwei Zeilen hoch, der Rest auf der Grundlinie.
|
|
96
|
+
// `ch` im Span misst die doppelte Schrift, darum die halbe Zahl.
|
|
97
|
+
const n = b.doubleSizeLead;
|
|
98
|
+
return (_jsxs("div", { className: "keck-blatt-zeile keck-blatt-zeile--gross", style: { display: 'flex', alignItems: 'flex-end', whiteSpace: 'pre', height: '4ch', overflow: 'hidden', fontWeight: b.bold ? 'bold' : 'normal' }, children: [_jsx("span", { style: { fontSize: '2em', width: `${n / 2}ch`, lineHeight: '2ch', fontWeight: 'bold', textAlign: 'center', flex: 'none' }, children: b.text.slice(0, n).trim() }), _jsx("span", { style: { lineHeight: '2ch' }, children: b.text.slice(n) })] }, i));
|
|
99
|
+
}
|
|
93
100
|
return (_jsx("div", { className: "keck-blatt-zeile", style: { whiteSpace: 'pre', height: '2ch', lineHeight: '2ch', overflow: 'hidden', fontWeight: b.bold ? 'bold' : 'normal' }, children: b.text }, i));
|
|
94
101
|
case 'logo':
|
|
95
102
|
return (_jsx("div", { className: "keck-blatt-logo", style: { height: `${b.heightLines * 2}ch`, display: 'flex', justifyContent: 'center' }, children: logoUrl === undefined ? null : (_jsx("img", { src: logoUrl, alt: "", "aria-hidden": "true", style: { width: `${b.widthFraction * z}ch`, height: `${b.heightLines * 2}ch`, objectFit: 'contain' } })) }, i));
|
|
@@ -40,6 +40,15 @@ export type SheetBlock = {
|
|
|
40
40
|
readonly text: string;
|
|
41
41
|
readonly bold: boolean;
|
|
42
42
|
readonly blank: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Die ersten n Spalten sind EINE Zelle, deren Inhalt (ohne Leerraum)
|
|
45
|
+
* doppelt breit und doppelt hoch steht -- die Zeile ist dann zwei
|
|
46
|
+
* Zeilen hoch. Nur das Testblatt des Zeichensatzes setzt das (Nummern
|
|
47
|
+
* links); fehlt es, ist alles einfach gross. Ein Zeichner, der das Feld
|
|
48
|
+
* nicht kennt, zeigt die Zeile in einfacher Groesse, die Spalten
|
|
49
|
+
* bleiben dieselben.
|
|
50
|
+
*/
|
|
51
|
+
readonly doubleSizeLead?: number;
|
|
43
52
|
} | {
|
|
44
53
|
readonly kind: 'logo';
|
|
45
54
|
readonly widthFraction: number;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Erzeugt von scripts/zeichensatz-vorlage.py -- nicht von Hand aendern.
|
|
2
|
+
// Schrift: Menlo Regular 20 px (sha256 dc256e0b39c2a6fec947129d421fef41b8b429f58f9b6e5d1b148c87f775c1f6), Schwelle 160.
|
|
3
|
+
/** Die Vorlage-Zeile als Rasterbild: 384 x 24 Punkte, MSB zuerst, je Zeile auf volle Bytes aufgefuellt; base64. */
|
|
4
|
+
export const CODE_TABLE_REFERENCE_RASTER = {
|
|
5
|
+
width: 384,
|
|
6
|
+
height: 24,
|
|
7
|
+
bits: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGYAAGYAAGYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGYAAGYAAGYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGYAAGYAAGYAABgAADwAAIEAAH4AAB8AAD4AADwAAAAAAAAAAAAAAAAAAAAAAAAAAGYAAGYAAGYAADwAAH4AAcOAAOcAAD8AAH4AAH4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAAMMAAcOAAMMAAHAAAGAAAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAAMMAAcOAAMMAAOAAAGAAAEIAAAAAAAAAAAAAAAAAAAAAAAAAAP4AAH4AAMMAAGYAAcOAAcOAAMwAAMAAAHAAAGYAAAAAAAAAAAAAAAAAAAAAAAAAAOcAAOcAAMMAAGYAAYGAAcOAANgAAfwAAHgAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAMMAAMMAAGYAAYGAAcOAANgAAfwAAM4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAcOAAMMAAGcAAYGAAcOAANwAAMAAAMcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH8AAYGAAMMAAMMAAYGAAcOAAM4AAfgAAMMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAYGAAMMAAP8AAYGAAcOAAMcAA/gAAOMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcMAAYGAAMMAAP8AAcGAAcOAAMGAAMAAAHsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYMAAcOAAMMAAcOAAcOAAcOAAMGAAOAAAB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYMAAMMAAMMAAYGAAMMAAMMAAMGAAGAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO8AAOcAAP8AAYGAAP8AAP8AAPOAAH8AAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAH4AAH8AA4HAAH4AAH4AAP8AAD8AAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
|
8
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Das Testblatt fuer den Zeichensatz: welche Code-Tabelle druckt auf diesem
|
|
3
|
+
* Drucker die Umlaute richtig?
|
|
4
|
+
*
|
|
5
|
+
* Oben steht die Vorlage-Zeile als Rasterbild -- ein Bild druckt jeder
|
|
6
|
+
* Drucker gleich, egal welche Tabelle er gerade hat. Darunter je Tabelle des
|
|
7
|
+
* Katalogs eine Zeile mit ihrer Nummer (gross), umgeschaltet mit `ESC t n`
|
|
8
|
+
* und mit den Bytes dieser Tabelle. Die erste Zeile, die aussieht wie die
|
|
9
|
+
* Vorlage, ist die richtige; Zeile 6 (Ersatzbuchstaben) passt immer.
|
|
10
|
+
*
|
|
11
|
+
* Bildschirm und Papier zeigen dasselbe Blatt: `codeTableTestSheet` liefert
|
|
12
|
+
* es im Zeilenmodell des Beleg-Blatts (`ReceiptSheet`), `codeTableTestSheetBytes`
|
|
13
|
+
* druckt genau diese Zeilen. Das Blatt hat immer 32 Spalten (58 mm); auf
|
|
14
|
+
* 80 mm steht der Block ueber den linken Rand (`GS L`) mittig.
|
|
15
|
+
*
|
|
16
|
+
* Gemeinsamer Prueffall mit dem Dart-Zwilling:
|
|
17
|
+
* `fixtures/expected/code-table-test-sheet.{mm58,mm80}.hex` und `.lines.json`.
|
|
18
|
+
*/
|
|
19
|
+
import type { ReceiptSheet } from './blatt.js';
|
|
20
|
+
import { type CodeTable, type CodeTableId } from '../printing/code-tables.js';
|
|
21
|
+
import { type PosPaperSize, type RasterImage } from '../printing/escpos.js';
|
|
22
|
+
/** Spalten des Testblatts -- immer 58-mm-Format. */
|
|
23
|
+
export declare const CODE_TABLE_TEST_SHEET_CHARS = 32;
|
|
24
|
+
export interface CodeTableTestSheetInput {
|
|
25
|
+
/** Kassen-Kennung fuer die Kopfzeile (keine Personendaten). */
|
|
26
|
+
cashregisterLabel: string;
|
|
27
|
+
/** Zeitpunkt des Drucks; die Kopfzeile zeigt ihn in Wiener Zeit. */
|
|
28
|
+
time: Date;
|
|
29
|
+
/** Papier des Druckers; das Blatt bleibt 32 Spalten, auf 80 mm mittig. */
|
|
30
|
+
paper: PosPaperSize;
|
|
31
|
+
}
|
|
32
|
+
/** Eine Testzeile: Nummer, Tabelle und die Zeichen, die ihr fehlen (fuer „ohne €“ am Bildschirm). */
|
|
33
|
+
export interface CodeTableTestSheetRow {
|
|
34
|
+
readonly number: CodeTable['number'];
|
|
35
|
+
readonly codeTable: CodeTableId;
|
|
36
|
+
readonly missing: readonly string[];
|
|
37
|
+
}
|
|
38
|
+
/** Das Testblatt im Zeilenmodell des Beleg-Blatts, dazu die Testzeilen. */
|
|
39
|
+
export interface CodeTableTestSheet extends ReceiptSheet {
|
|
40
|
+
readonly rows: readonly CodeTableTestSheetRow[];
|
|
41
|
+
}
|
|
42
|
+
/** Die Vorlage-Zeile als Rasterbild (384 x 24 Punkte), wie sie am Papier steht. */
|
|
43
|
+
export declare function codeTableReferenceImage(): RasterImage;
|
|
44
|
+
/** Das Testblatt im Zeilenmodell des Beleg-Blatts -- dieselben Zeilen wie am Papier. */
|
|
45
|
+
export declare function codeTableTestSheet(options: CodeTableTestSheetInput): CodeTableTestSheet;
|
|
46
|
+
/**
|
|
47
|
+
* Das Testblatt als ESC/POS-Bytes. Jede Testzeile schaltet nach ihrer
|
|
48
|
+
* Nummer einmal mit `FS .` + `ESC t n` auf ihre Tabelle und traegt deren Bytes (`encodeForCodeTable`,
|
|
49
|
+
* also das echte €-Byte, wo die Tabelle es hat). Die Nummer steht doppelt
|
|
50
|
+
* breit und hoch (`GS !`), die Vorlage als Rasterbild (`GS v 0`).
|
|
51
|
+
*/
|
|
52
|
+
export declare function codeTableTestSheetBytes(options: CodeTableTestSheetInput): Uint8Array;
|