@naphatjm/cdh-thermal-printer 1.0.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/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # CDH Thermal Printer
2
+
3
+ A JavaScript library for controlling ESC/POS thermal printers with support for Thai text rendering.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install cdh-thermal-printer
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Basic Setup
14
+
15
+ ```javascript
16
+ import { ThermalPrinter } from "cdh-thermal-printer";
17
+
18
+ const printer = new ThermalPrinter("http://localhost:9123", 384);
19
+
20
+ printer
21
+ .init()
22
+ .align(1) // center
23
+ .bold(true)
24
+ .printThaiText("สวัสดีครับ")
25
+ .feed(2)
26
+ .cut()
27
+ .print("Printer Name");
28
+ ```
29
+
30
+ ## ⚠️ Important: Font Setup for Thai Text
31
+
32
+ When using `printThaiText()`, you **must** load the Sarabun font in your HTML file:
33
+
34
+ ```html
35
+ <link
36
+ href="https://fonts.googleapis.com/css2?family=Sarabun:wght@400;700&display=swap"
37
+ rel="stylesheet" />
38
+ ```
39
+
40
+ Without this link, the printer will use the default system font instead of Sarabun.
41
+
42
+ ## API
43
+
44
+ ### Constructor
45
+
46
+ ```javascript
47
+ new ThermalPrinter((driverApiUrl = "http://localhost:9123"), (width = 384));
48
+ ```
49
+
50
+ - `driverApiUrl`: URL of the thermal printer driver API
51
+ - `width`: Printer width in dots (384 = 58mm, 576 = 80mm)
52
+
53
+ ### Methods
54
+
55
+ - `init()` - Initialize printer
56
+ - `align(alignment)` - Set text alignment (0=Left, 1=Center, 2=Right)
57
+ - `bold(enable)` - Enable/disable bold text
58
+ - `feed(lines)` - Feed paper by specified lines
59
+ - `cut(partial)` - Cut paper (partial or full)
60
+ - `image(imageData)` - Print image from canvas ImageData
61
+ - `printThaiText(text, fontSize)` - Print Thai text (automatically renders as image)
62
+ - `clear()` - Clear buffer
63
+ - `getBuffer()` - Get current buffer as Uint8Array
64
+ - `print(printerName)` - Send buffer to printer
65
+ - `static getPrinters(apiUrl)` - Get list of available printers
@@ -0,0 +1,119 @@
1
+ const o = {
2
+ LF: 10,
3
+ // Commands
4
+ INIT: [27, 64],
5
+ // Initialize printer
6
+ CUT_FULL: [29, 86, 66, 0],
7
+ // Full cut
8
+ CUT_PARTIAL: [29, 86, 65, 0],
9
+ // Partial cut
10
+ // Formatting
11
+ BOLD_ON: [27, 69, 1],
12
+ BOLD_OFF: [27, 69, 0],
13
+ ALIGN_LEFT: [27, 97, 0]
14
+ };
15
+ function p(u) {
16
+ const e = u.width, t = u.height, s = u.data, r = e / 8;
17
+ let n = [];
18
+ n.push(29, 118, 48, 0), n.push(r % 256, Math.floor(r / 256)), n.push(t % 256, Math.floor(t / 256));
19
+ for (let h = 0; h < t; h++)
20
+ for (let c = 0; c < r; c++) {
21
+ let f = 0;
22
+ for (let i = 0; i < 8; i++) {
23
+ const a = (h * e + c * 8 + i) * 4;
24
+ s[a] + s[a + 1] + s[a + 2] < 380 && (f |= 1 << 7 - i);
25
+ }
26
+ n.push(f);
27
+ }
28
+ return n;
29
+ }
30
+ class x {
31
+ constructor(e = "http://localhost:9123", t = 384) {
32
+ this.driverApi = e, this.printerWidth = t, this.buffer = [];
33
+ }
34
+ // --- Basic Commands ---
35
+ init() {
36
+ return this.buffer.push(...o.INIT), this;
37
+ }
38
+ align(e = 1) {
39
+ const t = [...o.ALIGN_LEFT];
40
+ return t[2] = e, this.buffer.push(...t), this;
41
+ }
42
+ bold(e = !0) {
43
+ return this.buffer.push(...e ? o.BOLD_ON : o.BOLD_OFF), this;
44
+ }
45
+ feed(e = 1) {
46
+ for (let t = 0; t < e; t++) this.buffer.push(o.LF);
47
+ return this;
48
+ }
49
+ cut(e = !1) {
50
+ return this.buffer.push(...e ? o.CUT_PARTIAL : o.CUT_FULL), this;
51
+ }
52
+ // --- Image & Thai Text Logic ---
53
+ image(e) {
54
+ const t = p(e);
55
+ return this.buffer.push(...t), this;
56
+ }
57
+ /**
58
+ * พิมพ์ข้อความภาษาไทย (Render เป็นรูปภาพอัตโนมัติ)
59
+ *
60
+ * ⚠️ REQUIRED: Sarabun font must be loaded in your HTML file:
61
+ * <link href="https://fonts.googleapis.com/css2?family=Sarabun:wght@400;700&display=swap" rel="stylesheet">
62
+ *
63
+ * Without this link, the system will use the default font instead.
64
+ *
65
+ * @param {string} text - Thai text to print
66
+ * @param {number} fontSize - Font size in pixels (default: 22)
67
+ */
68
+ printThaiText(e, t = 22) {
69
+ if (typeof document > "u")
70
+ return console.error("Browser environment required for printThaiText"), this;
71
+ const s = document.createElement("canvas"), r = s.getContext("2d"), n = "'Sarabun', sans-serif", h = t + 12, c = e.split(`
72
+ `), f = c.length * h + 20;
73
+ s.width = this.printerWidth, s.height = f, r.fillStyle = "white", r.fillRect(0, 0, s.width, s.height), r.fillStyle = "black", r.font = `${t}px ${n}`, r.textBaseline = "top";
74
+ let i = 10;
75
+ for (let l of c)
76
+ r.fillText(l, 10, i), i += h;
77
+ const a = r.getImageData(0, 0, this.printerWidth, f);
78
+ return this.image(a);
79
+ }
80
+ // --- Execution ---
81
+ clear() {
82
+ return this.buffer = [], this;
83
+ }
84
+ getBuffer() {
85
+ return new Uint8Array(this.buffer);
86
+ }
87
+ async print(e) {
88
+ if (!e) {
89
+ const t = await x.getPrinters(this.driverApi);
90
+ if (t.length > 0) e = t[0];
91
+ else throw new Error("No printer found.");
92
+ }
93
+ try {
94
+ const t = this.getBuffer(), s = encodeURIComponent(e);
95
+ if (!(await fetch(
96
+ `${this.driverApi}/print?printer=${s}`,
97
+ {
98
+ method: "POST",
99
+ headers: { "Content-Type": "application/octet-stream" },
100
+ body: t
101
+ }
102
+ )).ok) throw new Error("Driver Error");
103
+ return this.clear(), { success: !0 };
104
+ } catch (t) {
105
+ throw console.error("Print Failed:", t), t;
106
+ }
107
+ }
108
+ // --- Static Methods ---
109
+ static async getPrinters(e = "http://localhost:9123") {
110
+ try {
111
+ return await (await fetch(`${e}/printers`)).json();
112
+ } catch (t) {
113
+ return console.error("Connection Error:", t), [];
114
+ }
115
+ }
116
+ }
117
+ export {
118
+ x as ThermalPrinter
119
+ };
@@ -0,0 +1,2 @@
1
+ (function(h,n){typeof exports=="object"&&typeof module<"u"?n(exports):typeof define=="function"&&define.amd?define(["exports"],n):(h=typeof globalThis<"u"?globalThis:h||self,n(h.ThermalPrinter={}))})(this,(function(h){"use strict";const n={LF:10,INIT:[27,64],CUT_FULL:[29,86,66,0],CUT_PARTIAL:[29,86,65,0],BOLD_ON:[27,69,1],BOLD_OFF:[27,69,0],ALIGN_LEFT:[27,97,0]};function x(d){const e=d.width,t=d.height,i=d.data,r=e/8;let s=[];s.push(29,118,48,0),s.push(r%256,Math.floor(r/256)),s.push(t%256,Math.floor(t/256));for(let c=0;c<t;c++)for(let f=0;f<r;f++){let u=0;for(let o=0;o<8;o++){const l=(c*e+f*8+o)*4;i[l]+i[l+1]+i[l+2]<380&&(u|=1<<7-o)}s.push(u)}return s}class a{constructor(e="http://localhost:9123",t=384){this.driverApi=e,this.printerWidth=t,this.buffer=[]}init(){return this.buffer.push(...n.INIT),this}align(e=1){const t=[...n.ALIGN_LEFT];return t[2]=e,this.buffer.push(...t),this}bold(e=!0){return this.buffer.push(...e?n.BOLD_ON:n.BOLD_OFF),this}feed(e=1){for(let t=0;t<e;t++)this.buffer.push(n.LF);return this}cut(e=!1){return this.buffer.push(...e?n.CUT_PARTIAL:n.CUT_FULL),this}image(e){const t=x(e);return this.buffer.push(...t),this}printThaiText(e,t=22){if(typeof document>"u")return console.error("Browser environment required for printThaiText"),this;const i=document.createElement("canvas"),r=i.getContext("2d"),s="'Sarabun', sans-serif",c=t+12,f=e.split(`
2
+ `),u=f.length*c+20;i.width=this.printerWidth,i.height=u,r.fillStyle="white",r.fillRect(0,0,i.width,i.height),r.fillStyle="black",r.font=`${t}px ${s}`,r.textBaseline="top";let o=10;for(let p of f)r.fillText(p,10,o),o+=c;const l=r.getImageData(0,0,this.printerWidth,u);return this.image(l)}clear(){return this.buffer=[],this}getBuffer(){return new Uint8Array(this.buffer)}async print(e){if(!e){const t=await a.getPrinters(this.driverApi);if(t.length>0)e=t[0];else throw new Error("No printer found.")}try{const t=this.getBuffer(),i=encodeURIComponent(e);if(!(await fetch(`${this.driverApi}/print?printer=${i}`,{method:"POST",headers:{"Content-Type":"application/octet-stream"},body:t})).ok)throw new Error("Driver Error");return this.clear(),{success:!0}}catch(t){throw console.error("Print Failed:",t),t}}static async getPrinters(e="http://localhost:9123"){try{return await(await fetch(`${e}/printers`)).json()}catch(t){return console.error("Connection Error:",t),[]}}}h.ThermalPrinter=a,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})}));
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@naphatjm/cdh-thermal-printer",
3
+ "version": "1.0.0",
4
+ "description": "Thai Thermal Printer Library via Local Driver",
5
+ "type": "module",
6
+ "files": [
7
+ "dist"
8
+ ],
9
+ "main": "./dist/thermal-printer.umd.js",
10
+ "module": "./dist/thermal-printer.es.js",
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/thermal-printer.es.js",
14
+ "require": "./dist/thermal-printer.umd.js"
15
+ }
16
+ },
17
+ "scripts": {
18
+ "dev": "vite",
19
+ "build": "vite build",
20
+ "preview": "vite preview"
21
+ },
22
+ "keywords": [
23
+ "thermal",
24
+ "printer",
25
+ "escpos",
26
+ "thai",
27
+ "driver"
28
+ ],
29
+ "author": "CDH",
30
+ "license": "ISC",
31
+ "devDependencies": {
32
+ "vite": "^7.3.1"
33
+ }
34
+ }