@thermal-print/escpos 0.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.
Files changed (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +193 -0
  3. package/dist/command-adapters/escbematech-adapter.d.ts +30 -0
  4. package/dist/command-adapters/escbematech-adapter.d.ts.map +1 -0
  5. package/dist/command-adapters/escbematech-adapter.js +175 -0
  6. package/dist/command-adapters/escpos-adapter.d.ts +25 -0
  7. package/dist/command-adapters/escpos-adapter.d.ts.map +1 -0
  8. package/dist/command-adapters/escpos-adapter.js +144 -0
  9. package/dist/command-adapters/index.d.ts +11 -0
  10. package/dist/command-adapters/index.d.ts.map +1 -0
  11. package/dist/command-adapters/index.js +14 -0
  12. package/dist/command-adapters/types.d.ts +78 -0
  13. package/dist/command-adapters/types.d.ts.map +1 -0
  14. package/dist/command-adapters/types.js +8 -0
  15. package/dist/commands/escbematech.d.ts +867 -0
  16. package/dist/commands/escbematech.d.ts.map +1 -0
  17. package/dist/commands/escbematech.js +1387 -0
  18. package/dist/commands/escpos.d.ts +582 -0
  19. package/dist/commands/escpos.d.ts.map +1 -0
  20. package/dist/commands/escpos.js +1048 -0
  21. package/dist/converter.d.ts +47 -0
  22. package/dist/converter.d.ts.map +1 -0
  23. package/dist/converter.js +92 -0
  24. package/dist/encodings/cp860.d.ts +25 -0
  25. package/dist/encodings/cp860.d.ts.map +1 -0
  26. package/dist/encodings/cp860.js +187 -0
  27. package/dist/generator.d.ts +118 -0
  28. package/dist/generator.d.ts.map +1 -0
  29. package/dist/generator.js +383 -0
  30. package/dist/index.d.ts +17 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +55 -0
  33. package/dist/styles.d.ts +72 -0
  34. package/dist/styles.d.ts.map +1 -0
  35. package/dist/styles.js +210 -0
  36. package/dist/traverser.d.ts +60 -0
  37. package/dist/traverser.d.ts.map +1 -0
  38. package/dist/traverser.js +285 -0
  39. package/dist/types.d.ts +21 -0
  40. package/dist/types.d.ts.map +1 -0
  41. package/dist/types.js +5 -0
  42. package/package.json +31 -0
package/dist/styles.js ADDED
@@ -0,0 +1,210 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractTextStyle = extractTextStyle;
4
+ exports.extractViewStyle = extractViewStyle;
5
+ exports.isBold = isBold;
6
+ exports.mapFontSizeToESCPOS = mapFontSizeToESCPOS;
7
+ exports.mapTextAlign = mapTextAlign;
8
+ exports.calculateSpacing = calculateSpacing;
9
+ exports.isDashedBorder = isDashedBorder;
10
+ exports.generateDividerLine = generateDividerLine;
11
+ exports.mergeStyles = mergeStyles;
12
+ exports.parseWidth = parseWidth;
13
+ exports.alignTextInColumn = alignTextInColumn;
14
+ exports.wrapText = wrapText;
15
+ const cp860_1 = require("./encodings/cp860");
16
+ /**
17
+ * Extracts text style from a style object
18
+ */
19
+ function extractTextStyle(style) {
20
+ return {
21
+ fontSize: style?.fontSize,
22
+ fontWeight: style?.fontWeight,
23
+ fontFamily: style?.fontFamily,
24
+ textAlign: style?.textAlign || "left",
25
+ };
26
+ }
27
+ /**
28
+ * Extracts view/layout style from a style object
29
+ */
30
+ function extractViewStyle(style) {
31
+ return {
32
+ display: style?.display,
33
+ flexDirection: style?.flexDirection || "column",
34
+ justifyContent: style?.justifyContent,
35
+ alignItems: style?.alignItems,
36
+ padding: style?.padding,
37
+ paddingTop: style?.paddingTop,
38
+ paddingBottom: style?.paddingBottom,
39
+ paddingLeft: style?.paddingLeft,
40
+ paddingRight: style?.paddingRight,
41
+ margin: style?.margin,
42
+ marginTop: style?.marginTop,
43
+ marginBottom: style?.marginBottom,
44
+ marginLeft: style?.marginLeft,
45
+ marginRight: style?.marginRight,
46
+ borderBottom: style?.borderBottom,
47
+ borderTop: style?.borderTop,
48
+ width: style?.width,
49
+ };
50
+ }
51
+ /**
52
+ * Determines if text should be bold
53
+ */
54
+ function isBold(style) {
55
+ return (style.fontWeight === "bold" ||
56
+ style.fontWeight === 700 ||
57
+ style.fontWeight === "Helvetica-Bold" ||
58
+ style.fontFamily === "Helvetica-Bold");
59
+ }
60
+ /**
61
+ * Maps fontSize to ESC/POS character size (width x height multipliers)
62
+ *
63
+ * Font size mapping using ESC ! command (limited to 2x2 maximum):
64
+ * - 8-12px → 1x1 (normal)
65
+ * - 13-18px → 1x2 (normal width, double height)
66
+ * - 19-24px → 2x1 (double width, normal height)
67
+ * - 25+px → 2x2 (double width, double height)
68
+ *
69
+ * Note: ESC ! command only supports up to 2x2 character size.
70
+ * Larger sizes (3x, 4x, etc.) would require GS ! command which may not
71
+ * be supported on all thermal printers (e.g., Bematech MP-4200 TH).
72
+ *
73
+ * PDF uses zoom factor (default 0.46), so actual sizes are smaller:
74
+ * - 16 * 0.46 = 7.36 (normal text)
75
+ * - 18 * 0.46 = 8.28 (medium text)
76
+ * - 20 * 0.46 = 9.2 (title text)
77
+ *
78
+ * We use raw fontSize values (ignoring zoom) for better differentiation
79
+ */
80
+ function mapFontSizeToESCPOS(fontSize) {
81
+ // Default to 1x1 (normal size)
82
+ if (!fontSize)
83
+ return { width: 1, height: 1 };
84
+ // Parse fontSize if it's a string (e.g., "8.28px")
85
+ const size = typeof fontSize === "string" ? parseFloat(fontSize) : fontSize;
86
+ if (isNaN(size))
87
+ return { width: 1, height: 1 };
88
+ // Map font size to character multipliers (max 2x2 for ESC ! compatibility)
89
+ if (size >= 25)
90
+ return { width: 2, height: 2 }; // 25+px → 2x2 (maximum)
91
+ if (size >= 19)
92
+ return { width: 2, height: 1 }; // 19-24px → 2x1
93
+ if (size >= 13)
94
+ return { width: 1, height: 2 }; // 13-18px → 1x2
95
+ return { width: 1, height: 1 }; // 8-12px → 1x1 (normal)
96
+ }
97
+ /**
98
+ * Maps textAlign to ESC/POS alignment
99
+ */
100
+ function mapTextAlign(textAlign) {
101
+ if (textAlign === "center")
102
+ return "center";
103
+ if (textAlign === "right")
104
+ return "right";
105
+ return "left";
106
+ }
107
+ /**
108
+ * Calculates spacing (margin/padding) in lines
109
+ * Approximates pixels to line feeds
110
+ */
111
+ function calculateSpacing(value) {
112
+ if (!value)
113
+ return 0;
114
+ // Rough approximation: ~20 pixels = 1 line feed
115
+ return Math.round(value / 20);
116
+ }
117
+ /**
118
+ * Determines if a border is dashed
119
+ */
120
+ function isDashedBorder(border) {
121
+ return border?.includes("dashed") ?? false;
122
+ }
123
+ /**
124
+ * Generates a divider line based on border style
125
+ */
126
+ function generateDividerLine(width, dashed = false) {
127
+ const char = dashed ? "-" : "─";
128
+ return char.repeat(width);
129
+ }
130
+ /**
131
+ * Merges multiple style objects (handles spread syntax)
132
+ */
133
+ function mergeStyles(...styles) {
134
+ return Object.assign({}, ...styles.filter((s) => s));
135
+ }
136
+ /**
137
+ * Parses width percentage to column width in characters
138
+ * Uses Math.round() to minimize rounding errors
139
+ */
140
+ function parseWidth(width, totalWidth) {
141
+ if (!width)
142
+ return totalWidth;
143
+ if (typeof width === "number")
144
+ return width;
145
+ if (typeof width === "string") {
146
+ if (width.includes("%")) {
147
+ const percentage = parseInt(width.replace("%", ""));
148
+ return Math.round((percentage / 100) * totalWidth);
149
+ }
150
+ }
151
+ return totalWidth;
152
+ }
153
+ /**
154
+ * Aligns text within a column width (using CP860 byte length for accurate padding)
155
+ */
156
+ function alignTextInColumn(text, width, align) {
157
+ // Get actual byte length when encoded to CP860
158
+ let encodedLength = (0, cp860_1.encodeCP860)(text).length;
159
+ let truncatedText = text;
160
+ // Truncate if too long (character by character until it fits)
161
+ while (encodedLength > width && truncatedText.length > 0) {
162
+ truncatedText = truncatedText.substring(0, truncatedText.length - 1);
163
+ encodedLength = (0, cp860_1.encodeCP860)(truncatedText).length;
164
+ }
165
+ // Calculate padding based on actual encoded byte length
166
+ const padding = width - encodedLength;
167
+ // Already fits perfectly
168
+ if (padding === 0) {
169
+ return truncatedText;
170
+ }
171
+ // Pad based on alignment
172
+ if (align === "right") {
173
+ return " ".repeat(padding) + truncatedText;
174
+ }
175
+ else if (align === "center") {
176
+ const leftPad = Math.floor(padding / 2);
177
+ const rightPad = padding - leftPad;
178
+ return " ".repeat(leftPad) + truncatedText + " ".repeat(rightPad);
179
+ }
180
+ else {
181
+ // left align
182
+ return truncatedText + " ".repeat(padding);
183
+ }
184
+ }
185
+ /**
186
+ * Splits text into multiple lines if it exceeds width
187
+ */
188
+ function wrapText(text, width) {
189
+ if (text.length <= width) {
190
+ return [text];
191
+ }
192
+ const lines = [];
193
+ let currentLine = "";
194
+ const words = text.split(" ");
195
+ for (const word of words) {
196
+ if ((currentLine + " " + word).trim().length <= width) {
197
+ currentLine = (currentLine + " " + word).trim();
198
+ }
199
+ else {
200
+ if (currentLine) {
201
+ lines.push(currentLine);
202
+ }
203
+ currentLine = word;
204
+ }
205
+ }
206
+ if (currentLine) {
207
+ lines.push(currentLine);
208
+ }
209
+ return lines.length > 0 ? lines : [text.substring(0, width)];
210
+ }
@@ -0,0 +1,60 @@
1
+ import { ElementNode } from "@thermal-print/core";
2
+ import { ESCPOSGenerator } from "./generator";
3
+ /**
4
+ * Tree Traverser
5
+ * Walks through the element tree and generates ESC/POS commands
6
+ */
7
+ export declare class TreeTraverser {
8
+ private generator;
9
+ constructor(generator: ESCPOSGenerator);
10
+ /**
11
+ * Traverse the entire tree starting from root
12
+ */
13
+ traverse(node: ElementNode | null): Promise<void>;
14
+ /**
15
+ * Handle Document element
16
+ */
17
+ private handleDocument;
18
+ /**
19
+ * Handle Page element
20
+ */
21
+ private handlePage;
22
+ /**
23
+ * Handle View element (container with layout)
24
+ */
25
+ private handleView;
26
+ /**
27
+ * Handle column layout (stacked vertically)
28
+ * Adds newlines between sibling elements for proper spacing
29
+ */
30
+ private handleColumnLayout;
31
+ /**
32
+ * Handle row layout (side-by-side columns)
33
+ */
34
+ private handleRowLayout;
35
+ /**
36
+ * Find the first Text node in a tree
37
+ */
38
+ private findFirstTextNode;
39
+ /**
40
+ * Collect text content from a node and its children
41
+ */
42
+ private collectTextContent;
43
+ /**
44
+ * Handle Text element
45
+ */
46
+ private handleText;
47
+ /**
48
+ * Handle TextNode (raw text)
49
+ */
50
+ private handleTextNode;
51
+ /**
52
+ * Handle Image element
53
+ */
54
+ private handleImage;
55
+ /**
56
+ * Traverse children nodes
57
+ */
58
+ private traverseChildren;
59
+ }
60
+ //# sourceMappingURL=traverser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traverser.d.ts","sourceRoot":"","sources":["../src/traverser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C;;;GAGG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAkB;gBAEvB,SAAS,EAAE,eAAe;IAItC;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BvD;;OAEG;YACW,cAAc;IAO5B;;OAEG;YACW,UAAU;IAIxB;;OAEG;YACW,UAAU;IAkBxB;;;OAGG;YACW,kBAAkB;IAchC;;OAEG;YACW,eAAe;IA+F7B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAczB;;OAEG;YACW,kBAAkB;IAmBhC;;OAEG;YACW,UAAU;IAgCxB;;OAEG;YACW,cAAc;IAM5B;;OAEG;YACW,WAAW;IA+BzB;;OAEG;YACW,gBAAgB;CAK/B"}
@@ -0,0 +1,285 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TreeTraverser = void 0;
4
+ const styles_1 = require("./styles");
5
+ /**
6
+ * Tree Traverser
7
+ * Walks through the element tree and generates ESC/POS commands
8
+ */
9
+ class TreeTraverser {
10
+ constructor(generator) {
11
+ this.generator = generator;
12
+ }
13
+ /**
14
+ * Traverse the entire tree starting from root
15
+ */
16
+ async traverse(node) {
17
+ if (!node)
18
+ return;
19
+ // Work with lowercase normalized types
20
+ const nodeType = node.type.toLowerCase();
21
+ switch (nodeType) {
22
+ case "document":
23
+ await this.handleDocument(node);
24
+ break;
25
+ case "page":
26
+ await this.handlePage(node);
27
+ break;
28
+ case "view":
29
+ await this.handleView(node);
30
+ break;
31
+ case "text":
32
+ await this.handleText(node);
33
+ break;
34
+ case "textnode":
35
+ await this.handleTextNode(node);
36
+ break;
37
+ case "image":
38
+ await this.handleImage(node);
39
+ break;
40
+ default:
41
+ // Unknown element, traverse children
42
+ await this.traverseChildren(node);
43
+ }
44
+ }
45
+ /**
46
+ * Handle Document element
47
+ */
48
+ async handleDocument(node) {
49
+ this.generator.initialize();
50
+ await this.traverseChildren(node);
51
+ // Add 6 blank lines at end for paper feed spacing
52
+ this.generator.addNewline(2);
53
+ }
54
+ /**
55
+ * Handle Page element
56
+ */
57
+ async handlePage(node) {
58
+ await this.traverseChildren(node);
59
+ }
60
+ /**
61
+ * Handle View element (container with layout)
62
+ */
63
+ async handleView(node) {
64
+ const viewStyle = (0, styles_1.extractViewStyle)(node.style);
65
+ // Apply spacing before
66
+ this.generator.applyViewSpacing(node.style, "before");
67
+ // Handle different layout modes
68
+ if (viewStyle.flexDirection === "row") {
69
+ await this.handleRowLayout(node);
70
+ }
71
+ else {
72
+ // Column layout (default) - add spacing between children
73
+ await this.handleColumnLayout(node);
74
+ }
75
+ // Apply spacing after
76
+ this.generator.applyViewSpacing(node.style, "after");
77
+ }
78
+ /**
79
+ * Handle column layout (stacked vertically)
80
+ * Adds newlines between sibling elements for proper spacing
81
+ */
82
+ async handleColumnLayout(node) {
83
+ const children = node.children;
84
+ for (let i = 0; i < children.length; i++) {
85
+ await this.traverse(children[i]);
86
+ // Add newline after each child except the last one
87
+ // This ensures proper spacing between elements in column layout
88
+ // if (i < children.length - 1 && children[i].type.toLowerCase() === "view") {
89
+ // this.generator.addNewline();
90
+ // }
91
+ }
92
+ }
93
+ /**
94
+ * Handle row layout (side-by-side columns)
95
+ */
96
+ async handleRowLayout(node) {
97
+ const children = node.children;
98
+ if (children.length === 0)
99
+ return;
100
+ // If there's only 1 child, just render it normally (not as a row)
101
+ // This prevents nested column layouts from being flattened
102
+ if (children.length === 1) {
103
+ await this.traverse(children[0]);
104
+ return;
105
+ }
106
+ const viewStyle = (0, styles_1.extractViewStyle)(node.style);
107
+ const paperWidth = this.generator.getPaperWidth();
108
+ // Check layout justification mode
109
+ const isSpaceBetween = viewStyle.justifyContent === "space-between";
110
+ const isCentered = viewStyle.justifyContent === "center";
111
+ // Calculate column widths
112
+ const columns = [];
113
+ for (const child of children) {
114
+ const childStyle = (0, styles_1.extractViewStyle)(child.style);
115
+ const width = (0, styles_1.parseWidth)(childStyle.width, paperWidth);
116
+ // Collect text content from child
117
+ const content = await this.collectTextContent(child);
118
+ // Determine alignment - check for Text node textAlign first
119
+ let align = "left";
120
+ // Look for Text element with textAlign
121
+ const textNode = this.findFirstTextNode(child);
122
+ if (textNode && textNode.style) {
123
+ const textStyle = (0, styles_1.extractTextStyle)(textNode.style);
124
+ align = (0, styles_1.mapTextAlign)(textStyle.textAlign);
125
+ }
126
+ else {
127
+ // Fall back to View alignment
128
+ if (childStyle.alignItems === "center" || childStyle.justifyContent === "center") {
129
+ align = "center";
130
+ }
131
+ else if (childStyle.alignItems === "flex-end" || childStyle.justifyContent === "flex-end") {
132
+ align = "right";
133
+ }
134
+ }
135
+ columns.push({ node: child, width, content, align });
136
+ }
137
+ // Build row text
138
+ let rowText = "";
139
+ // Check if columns have explicit widths (table layout) or should use space-between
140
+ const hasExplicitWidths = columns.some((col) => {
141
+ const childStyle = (0, styles_1.extractViewStyle)(col.node.style);
142
+ return childStyle.width !== undefined;
143
+ });
144
+ if (isSpaceBetween && columns.length === 2 && !hasExplicitWidths) {
145
+ // Special handling for space-between layout (payment summary style) WITHOUT explicit widths
146
+ // Calculate space between
147
+ const usedSpace = columns[0].content.length + columns[1].content.length;
148
+ const gap = Math.max(1, paperWidth - usedSpace);
149
+ rowText = columns[0].content + " ".repeat(gap) + columns[1].content;
150
+ }
151
+ else if (isCentered && !hasExplicitWidths) {
152
+ // Center the entire row on the paper by calculating total content width
153
+ // and adding leading spaces
154
+ // Add spacing between columns (1 space per gap)
155
+ const spacingBetweenColumns = Math.max(0, columns.length - 1);
156
+ const totalContentWidth = columns.reduce((sum, col) => sum + col.content.length, 0) + spacingBetweenColumns;
157
+ // Calculate leading spaces to center the entire row
158
+ const leadingSpaces = Math.max(0, Math.floor((paperWidth - totalContentWidth) / 2));
159
+ // Build row with leading spaces (center entire row)
160
+ rowText = " ".repeat(leadingSpaces);
161
+ for (let i = 0; i < columns.length; i++) {
162
+ if (i > 0) {
163
+ rowText += " "; // Add space between columns
164
+ }
165
+ rowText += columns[i].content;
166
+ }
167
+ }
168
+ else {
169
+ // Normal column layout OR space-between with explicit widths (use column padding)
170
+ for (let i = 0; i < columns.length; i++) {
171
+ const col = columns[i];
172
+ const cellText = (0, styles_1.alignTextInColumn)(col.content, col.width, col.align);
173
+ rowText += cellText;
174
+ }
175
+ }
176
+ this.generator.addText(rowText);
177
+ this.generator.addNewline();
178
+ }
179
+ /**
180
+ * Find the first Text node in a tree
181
+ */
182
+ findFirstTextNode(node) {
183
+ const normalizedType = node.type.toLowerCase();
184
+ if (normalizedType === "text") {
185
+ return node;
186
+ }
187
+ for (const child of node.children) {
188
+ const found = this.findFirstTextNode(child);
189
+ if (found)
190
+ return found;
191
+ }
192
+ return null;
193
+ }
194
+ /**
195
+ * Collect text content from a node and its children
196
+ */
197
+ async collectTextContent(node) {
198
+ let text = "";
199
+ const normalizedType = node.type.toLowerCase();
200
+ if (normalizedType === "text" || normalizedType === "textnode") {
201
+ // Get text from props.children
202
+ if (node.props.children !== undefined) {
203
+ text += String(node.props.children);
204
+ }
205
+ }
206
+ // Recursively collect from children
207
+ for (const child of node.children) {
208
+ text += await this.collectTextContent(child);
209
+ }
210
+ return text;
211
+ }
212
+ /**
213
+ * Handle Text element
214
+ */
215
+ async handleText(node) {
216
+ // Merge styles from parent if needed
217
+ const style = (0, styles_1.mergeStyles)(node.style);
218
+ // Apply text styling (sets alignment, bold, size)
219
+ this.generator.applyTextStyle(style);
220
+ // Get text content
221
+ let textContent = "";
222
+ // Check props.children first
223
+ if (node.props.children !== undefined) {
224
+ if (typeof node.props.children === "string" || typeof node.props.children === "number") {
225
+ textContent = String(node.props.children);
226
+ }
227
+ }
228
+ // If we have direct text, print it
229
+ if (textContent) {
230
+ this.generator.addText(textContent);
231
+ }
232
+ // Traverse children (nested Text elements)
233
+ await this.traverseChildren(node);
234
+ // Reset formatting after text (especially bold)
235
+ this.generator.resetFormatting();
236
+ // Add newline after text element
237
+ this.generator.addNewline();
238
+ }
239
+ /**
240
+ * Handle TextNode (raw text)
241
+ */
242
+ async handleTextNode(node) {
243
+ if (node.props.children) {
244
+ this.generator.addText(String(node.props.children));
245
+ }
246
+ }
247
+ /**
248
+ * Handle Image element
249
+ */
250
+ async handleImage(node) {
251
+ const source = node.props.source || node.props.src;
252
+ if (source) {
253
+ // Apply alignment from style (check both node style and parent style)
254
+ const style = (0, styles_1.mergeStyles)(node.style);
255
+ const viewStyle = (0, styles_1.extractViewStyle)(style);
256
+ const textStyle = (0, styles_1.extractTextStyle)(style);
257
+ // Determine alignment from textAlign or justifyContent
258
+ let align = "left";
259
+ if (textStyle.textAlign) {
260
+ align = (0, styles_1.mapTextAlign)(textStyle.textAlign);
261
+ }
262
+ else if (viewStyle.justifyContent === "center" || viewStyle.alignItems === "center") {
263
+ align = "center";
264
+ }
265
+ else if (viewStyle.justifyContent === "flex-end" || viewStyle.alignItems === "flex-end") {
266
+ align = "right";
267
+ }
268
+ // Set alignment before adding image
269
+ this.generator.setAlign(align);
270
+ await this.generator.addImage(source);
271
+ // Reset alignment
272
+ this.generator.setAlign("left");
273
+ }
274
+ this.generator.addNewline();
275
+ }
276
+ /**
277
+ * Traverse children nodes
278
+ */
279
+ async traverseChildren(node) {
280
+ for (const child of node.children) {
281
+ await this.traverse(child);
282
+ }
283
+ }
284
+ }
285
+ exports.TreeTraverser = TreeTraverser;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * ESC/POS-specific type definitions
3
+ */
4
+ export interface ESCPOSCommand {
5
+ type: 'raw' | 'text' | 'feed' | 'cut' | 'image' | 'qr';
6
+ data?: any;
7
+ buffer?: Buffer;
8
+ }
9
+ export interface ConversionContext {
10
+ paperWidth: number;
11
+ currentAlign: 'left' | 'center' | 'right';
12
+ currentSize: {
13
+ width: number;
14
+ height: number;
15
+ };
16
+ currentBold: boolean;
17
+ encoding: string;
18
+ debug: boolean;
19
+ buffer: Buffer[];
20
+ }
21
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,IAAI,CAAC;IACvD,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC1C,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ /**
3
+ * ESC/POS-specific type definitions
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@thermal-print/escpos",
3
+ "version": "0.1.0",
4
+ "description": "ESC/POS command generation and thermal printer control",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "keywords": [
8
+ "thermal-printer",
9
+ "escpos",
10
+ "receipt-printer",
11
+ "pos"
12
+ ],
13
+ "author": "",
14
+ "license": "MIT",
15
+ "dependencies": {
16
+ "@thermal-print/core": "0.1.0"
17
+ },
18
+ "devDependencies": {
19
+ "typescript": "^5.0.0"
20
+ },
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "files": [
25
+ "dist"
26
+ ],
27
+ "scripts": {
28
+ "build": "tsc --build",
29
+ "build:watch": "tsc --build --watch"
30
+ }
31
+ }