├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .github ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── npm-publish.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── examples ├── package.json ├── src │ ├── basic.ts │ ├── network.ts │ ├── printBarCode.ts │ ├── printImage.ts │ ├── printTable.ts │ └── templates.ts ├── tsconfig.json └── yarn.lock ├── package.json ├── resources └── ESCPOS_Command_Manual.pdf ├── src ├── buffer-builder.ts ├── command.ts ├── escpos.ts ├── image.ts ├── index.ts ├── node-factory.ts ├── nodes │ ├── align-node.ts │ ├── barcode-node.ts │ ├── bold-node.ts │ ├── break-line-node.ts │ ├── document-node.ts │ ├── image-node.ts │ ├── line-feed-node.ts │ ├── open-cash-drawer-node.ts │ ├── paper-cut-node.ts │ ├── print-mode.ts │ ├── qrcode-node.ts │ ├── small-node.ts │ ├── text-line-node.ts │ ├── text-node.ts │ ├── underline-node.ts │ └── white-mode-node.ts ├── template-parser.ts ├── xml-node.ts └── xml-parser.ts ├── tsconfig.build.json ├── tsconfig.json ├── tslint.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent coding styles between different editors and IDEs 2 | # editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 2 9 | 10 | # We recommend you to keep these unchanged 11 | end_of_line = lf 12 | charset = utf-8 13 | trim_trailing_whitespace = true 14 | insert_final_newline = true 15 | 16 | [*.md] 17 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | **/lib 3 | eslint_report.json 4 | .nyc_output 5 | coverage 6 | .vscode 7 | jest.config.js 8 | *.d.ts -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "extends": [ 4 | "plugin:@typescript-eslint/recommended", 5 | "prettier", 6 | "prettier/@typescript-eslint" 7 | ], 8 | "plugins": ["@typescript-eslint"], 9 | "rules": { 10 | "no-trailing-spaces": "warn", 11 | "comma-dangle": "off", 12 | "quotes": [ 13 | "error", 14 | "single", 15 | { 16 | "avoidEscape": true 17 | } 18 | ], 19 | "semi": "warn", 20 | "@typescript-eslint/no-var-requires": "off", 21 | "@typescript-eslint/ban-types": "off", 22 | "@typescript-eslint/explicit-module-boundary-types": "off", 23 | "@typescript-eslint/ban-ts-ignore": "off", 24 | "@typescript-eslint/camelcase": "off" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | 4 | ## Related Issues 5 | 6 | 7 | 8 | 9 | Issue: #XXX 10 | 11 | ## How Has This Been Tested 12 | 13 | 14 | 15 | 16 | ## Types of changes 17 | 18 | 19 | - [ ] Bug fix (non-breaking change which fixes an issue) 20 | - [ ] New feature (non-breaking change which adds functionality) 21 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 22 | 23 | ## Checklist 24 | 25 | 26 | 27 | - [ ] My code follows the code style of this project. 28 | - [ ] My change requires a change to the documentation. 29 | - [ ] I have updated the documentation accordingly. 30 | - [ ] I have added tests to cover my changes. 31 | - [ ] All new and existing tests passed. 32 | 33 | ## Screenshots (if appropriate) 34 | -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | name: npm-publish 2 | on: 3 | push: 4 | tags: 5 | - 'v*.*.*' 6 | 7 | jobs: 8 | npm-publish: 9 | name: npm-publish 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout repository 13 | uses: actions/checkout@v2 14 | - uses: actions/setup-node@v1 15 | with: 16 | node-version: 12 17 | registry-url: https://registry.npmjs.org/ 18 | - name: Install Node Dependencies 19 | run: yarn install; cd examples; yarn install; cd .. 20 | - name: Build packages 21 | run: yarn build 22 | env: 23 | CI: "TRUE" 24 | - run: npm publish --access public 25 | env: 26 | NODE_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}} 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/lib 2 | **/node_modules 3 | coverage/* 4 | **/dist 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | **/build 3 | **/dist 4 | **/.github 5 | eslint_report.json 6 | .nyc_output 7 | coverage 8 | .vscode 9 | **/.jest 10 | .jest -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "all", 3 | "singleQuote": true, 4 | "semi": true, 5 | "tabWidth": 2, 6 | "useTabs": false, 7 | "arrowParens": "avoid", 8 | "endOfLine": "auto", 9 | "bracketSpacing": true 10 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "**/.git": true, 4 | "**/.github": true, 5 | "**/.hg": true, 6 | "**/CVS": true, 7 | "**/.DS_Store": true, 8 | "**/node_modules": true, 9 | "**/coverage": true, 10 | "**/lib": true, 11 | "**/yarn.lock": true, 12 | "**/dist": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Originally forked from [here](https://github.com/ingoncalves/escpos-xml) 2 | 3 | # ESC/POS XML 4 | 5 | Cross platform JavaScript library that implements the thermal printer ESC / POS protocol and provides an XML interface for preparing templates for printing. 6 | 7 | ## Features 8 | 9 | - [x] Text 10 | - [x] Text line 11 | - [x] Feed line 12 | - [x] Bold text 13 | - [x] Underline text 14 | - [x] Font size 15 | - [x] Small mode 16 | - [x] White mode 17 | - [x] Align 18 | - [x] Barcode 19 | - [x] QRcode 20 | - [x] Paper cut node 21 | - [x] Image (base64) (png only) 22 | - [x] XML with mustache 23 | 24 | 25 | ## Tested manually on following environments or platforms 26 | 27 | - [x] React Native (Android) 28 | - [x] React Native (iOS) 29 | - [x] React Native Web 30 | - [x] Server side (NodeJs) 31 | - [x] Desktop applications (nwjs & electron) 32 | - [x] Other node environment (terminal) 33 | 34 | 35 | ## Installation 36 | 37 | ```bash 38 | yarn add @tillpos/xml-escpos-helper 39 | ``` 40 | 41 | ## Examples 42 | 43 | ### With an XML template + plain object input (regular text). 44 | 45 | ```ts 46 | 47 | import { EscPos } from '@tillpos/xml-escpos-helper'; 48 | 49 | // store this template somewhere `s3` or as `static asset` based on your preference 50 | const template = ` 51 | 52 | 53 | 54 | 55 | {{title}} 56 | 57 | 58 | 59 | {{#thankyouNote}} 60 | 61 | {{{thankyouNote}}} 62 | 63 | 64 | 65 | 66 | 67 | 68 | `; 69 | 70 | const input = { 71 | title: 'Sample', 72 | thankyouNote: 'Welcome...!' 73 | }; 74 | 75 | const buffer = EscPos.getBufferFromTemplate(template, input); 76 | // send this buffer to a stream (eg.: bluetooth or wifi) 77 | 78 | ``` 79 | 80 | ### With an XML template + png image (base64) 81 | 82 | ```ts 83 | const template = ` 84 | 85 | 86 | 87 | {{title}} 88 | 89 | 90 | 91 | {{base64PngImage}} 92 | 93 | 94 | `; 95 | 96 | const input = { 97 | title: 'PNG - base64', 98 | base64PngImage: `data:image/png;base64,iVBORw0KGgoAAA+P/AaNn2GPEMgEFAAAAAElFTkSuQmCC` 99 | }; 100 | 101 | const buffer = EscPos.getBufferFromTemplate(template, input); 102 | ``` 103 | 104 | --- 105 | 106 | ## TODO 107 | 108 | - [ ] Font styles (font family) 109 | - [ ] Image bitmap conversion improvements 110 | - [ ] jpeg support 111 | - [ ] Add example apps to repo 112 | - [ ] Removed uglify for some reason, need to bring it back 113 | - [ ] Improve image rendering 114 | 115 | ## Common issues 116 | 117 | - If there is any delay you observe while printing with this library it is mostly due to image manipulations (try without image :mask: ) 118 | 119 | 120 | ## Useful links / resources 121 | 122 | - [ESC / POS Commands manual](./resources/ESCPOS_Command_Manual.pdf) 123 | - A [blog post](https://www.visuality.pl/posts/thermal-printer-protocols-for-image-and-text#:~:text=How%20can%20we%20print%20an,command%20language%20of%20thermal%20printers) explaiing about printing images with ESCPOS 124 | - Similar library for serverside - [node-escpos](https://github.com/song940/node-escpos). 125 | 126 | > Limitations on the react-native framework 127 | 128 | - [FileReader.readAsArrayBuffer](https://github.com/facebook/react-native/issues/21209) was not implemented. 129 | - Most of popular image manupulation libraries does not have support for react-native. eg : [jimp](https://www.npmjs.com/package/jimp), [jpeg-js](https://www.npmjs.com/package/jpeg-js) and [sharp](https://www.npmjs.com/package/sharp). We can use these libraries with some native node lib implemented in react native (some sort of polyfill). 130 | - For png this [library](https://github.com/photopea/UPNG.js) seems to be faster, but when tested this library with it, it is not retaining pixels at some places) 131 | - Use this [node-libs-react-native](https://www.npmjs.com/package/node-libs-react-native) if we need to use this library in react native (adds some mock or js implementation for fs, stream etc) 132 | 133 | --- 134 | 135 | Contributions of any kind welcome! :heart: 136 | 137 | -------------------------------------------------------------------------------- /examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "examples", 3 | "version": "1.0.0", 4 | "description": "Using in Nodejs env", 5 | "main": "index.js", 6 | "repository": "http://github.com/oolio-group/xml-escpos-helper.git", 7 | "license": "MIT", 8 | "private": false, 9 | "scripts": { 10 | "clean": "rm -rf ./dist && rm -rf ./tsconfig.build.tsbuildinfo", 11 | "compile": "yarn clean && tsc -p ./tsconfig.json", 12 | "print:basic": "yarn compile && yarn node ./dist/basic.js", 13 | "print:image": "yarn compile && yarn node ./dist/printImage.js", 14 | "print:table": "yarn compile && yarn node ./dist/printTable.js", 15 | "print:barcode": "yarn compile && yarn node ./dist/printBarcode.js" 16 | }, 17 | "dependencies": { 18 | "@tillpos/xml-escpos-helper": "^0.1.8", 19 | "table": "^6.6.0" 20 | }, 21 | "devDependencies": { 22 | "typescript": "^4.2.4" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/src/basic.ts: -------------------------------------------------------------------------------- 1 | import { sendDataToPrinter } from './network'; 2 | import { TEMPLATES } from './templates'; 3 | 4 | const printBasic = async () => { 5 | const input = { 6 | title: 'Sample', 7 | thankyouNote: 'Welcome...!' 8 | }; 9 | 10 | await sendDataToPrinter(input, TEMPLATES.BASIC); 11 | }; 12 | 13 | printBasic(); 14 | -------------------------------------------------------------------------------- /examples/src/network.ts: -------------------------------------------------------------------------------- 1 | import net from 'net'; 2 | import { EscPos } from '@tillpos/xml-escpos-helper'; 3 | const PRINTERS = [{ device_name: 'Epson', host: '192.168.0.8', port: 9100 }]; 4 | 5 | const connectToPrinter = ( 6 | host: string, 7 | port: number, 8 | buffer: Buffer, 9 | ): Promise => { 10 | return new Promise((res: (value: unknown) => void, rej) => { 11 | let device = new net.Socket(); 12 | 13 | device.on('close', () => { 14 | if (device) { 15 | device.destroy(); 16 | device = null; 17 | } 18 | res(true); 19 | return; 20 | }); 21 | 22 | device.on('error', rej); 23 | 24 | device.connect(port, host, () => { 25 | device.write(buffer); 26 | device.emit('close'); 27 | }); 28 | }); 29 | }; 30 | 31 | export const sendDataToPrinter = async (input: any, template: string) => { 32 | const { host, port } = PRINTERS[0]; 33 | const buffer = EscPos.getBufferFromTemplate(template, input); 34 | try { 35 | await connectToPrinter(host, port, (buffer as unknown) as Buffer); 36 | } catch (err) { 37 | console.log('some error', err); 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /examples/src/printBarCode.ts: -------------------------------------------------------------------------------- 1 | import { sendDataToPrinter } from './network'; 2 | import { TEMPLATES } from './templates'; 3 | 4 | const printBarCode = async () => { 5 | const input = { 6 | barcode: '12345678', 7 | }; 8 | 9 | await sendDataToPrinter(input, TEMPLATES.BAR_CODE); 10 | }; 11 | 12 | printBarCode(); 13 | -------------------------------------------------------------------------------- /examples/src/printImage.ts: -------------------------------------------------------------------------------- 1 | import { sendDataToPrinter } from './network'; 2 | import { TEMPLATES } from './templates'; 3 | 4 | const BASE64_PNG_IMAGE = `data:image/png;base64,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`; 5 | 6 | const printImage = async () => { 7 | const input = { 8 | title: 'Github', 9 | logo: BASE64_PNG_IMAGE 10 | }; 11 | 12 | await sendDataToPrinter(input, TEMPLATES.PNG_IMAGE); 13 | }; 14 | 15 | printImage(); 16 | -------------------------------------------------------------------------------- /examples/src/printTable.ts: -------------------------------------------------------------------------------- 1 | import { sendDataToPrinter } from './network'; 2 | import { TEMPLATES } from './templates'; 3 | import { getBorderCharacters, table } from 'table'; 4 | 5 | const printTable = async () => { 6 | const versions = [ 7 | ['React', '16.8'], 8 | ['Angular', '9'], 9 | ['Ember', '3.16'], 10 | ]; 11 | 12 | const tableData = table(versions, { 13 | border: getBorderCharacters(`void`), 14 | drawHorizontalLine: () => { 15 | return false; 16 | }, 17 | }); 18 | 19 | await sendDataToPrinter({ tableData }, TEMPLATES.TABLE); 20 | }; 21 | 22 | printTable(); 23 | -------------------------------------------------------------------------------- /examples/src/templates.ts: -------------------------------------------------------------------------------- 1 | export enum Templates { 2 | PNG_IMAGE = 'PNG_IMAGE', 3 | BASIC = 'BASIC', 4 | QR_CODE = 'QR_CODE', 5 | BAR_CODE = 'BAR_CODE', 6 | TABLE = 'TABLE', 7 | } 8 | 9 | export const TEMPLATES = { 10 | [Templates.BASIC]: ` 11 | 12 | 13 | 14 | {{title}} 15 | 16 | 17 | 18 | {{#thankyouNote}} 19 | 20 | {{{thankyouNote}}} 21 | 22 | {{/thankyouNote}} 23 | 24 | 25 | 26 | 27 | `, 28 | [Templates.PNG_IMAGE]: ` 29 | 30 | 31 | 32 | 33 | {{title}} 34 | 35 | 36 | 37 | {{logo}} 38 | 39 | 40 | `, 41 | [Templates.QR_CODE]: ` 42 | 43 | 44 | 45 | {{qrcode}} 46 | 47 | 48 | 49 | 50 | `, 51 | [Templates.BAR_CODE]: ` 52 | 53 | 54 | 55 | 56 | {{barcode}} 57 | 58 | 59 | 60 | `, 61 | [Templates.TABLE]: ` 62 | 63 | 64 | {{tableData}} 65 | 66 | `, 67 | } 68 | -------------------------------------------------------------------------------- /examples/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "esModuleInterop": true, 5 | "allowSyntheticDefaultImports": true, 6 | "target": "es6", 7 | "noImplicitAny": true, 8 | "moduleResolution": "node", 9 | "sourceMap": true, 10 | "outDir": "dist", 11 | "baseUrl": ".", 12 | "paths": { 13 | "*": [ 14 | "node_modules/*", 15 | "src/types/*" 16 | ] 17 | } 18 | }, 19 | "include": [ 20 | "src/**/*" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /examples/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@tillpos/xml-escpos-helper@^0.1.8": 6 | version "0.1.8" 7 | resolved "https://registry.yarnpkg.com/@tillpos/xml-escpos-helper/-/xml-escpos-helper-0.1.8.tgz#d3a664d776fa022516f7c85b0280706892e7fa5b" 8 | integrity sha512-2VdutlzFUcCMYxoJ7LmdK4l6/lWXA3TInwoWOdZ2cQKB0V0T3qogrHQGxKgRrlhFds2co0kksaa4ePj5QlFLCw== 9 | dependencies: 10 | buffer "^6.0.3" 11 | mustache "^4.1.0" 12 | mutable-buffer "2.0.3" 13 | ndarray "^1.0.19" 14 | pngjs "^6.0.0" 15 | xml-parser "^1.2.1" 16 | 17 | ajv@^8.0.1: 18 | version "8.2.0" 19 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.2.0.tgz#c89d3380a784ce81b2085f48811c4c101df4c602" 20 | integrity sha512-WSNGFuyWd//XO8n/m/EaOlNLtO0yL8EXT/74LqT4khdhpZjP7lkj/kT5uwRmGitKEVp/Oj7ZUHeGfPtgHhQ5CA== 21 | dependencies: 22 | fast-deep-equal "^3.1.1" 23 | json-schema-traverse "^1.0.0" 24 | require-from-string "^2.0.2" 25 | uri-js "^4.2.2" 26 | 27 | ansi-regex@^5.0.0: 28 | version "5.0.0" 29 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" 30 | integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== 31 | 32 | ansi-styles@^4.0.0: 33 | version "4.3.0" 34 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 35 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 36 | dependencies: 37 | color-convert "^2.0.1" 38 | 39 | astral-regex@^2.0.0: 40 | version "2.0.0" 41 | resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" 42 | integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== 43 | 44 | base64-js@^1.3.1: 45 | version "1.5.1" 46 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" 47 | integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== 48 | 49 | buffer@^6.0.3: 50 | version "6.0.3" 51 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" 52 | integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== 53 | dependencies: 54 | base64-js "^1.3.1" 55 | ieee754 "^1.2.1" 56 | 57 | color-convert@^2.0.1: 58 | version "2.0.1" 59 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 60 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 61 | dependencies: 62 | color-name "~1.1.4" 63 | 64 | color-name@~1.1.4: 65 | version "1.1.4" 66 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 67 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 68 | 69 | debug@^2.2.0: 70 | version "2.6.9" 71 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 72 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 73 | dependencies: 74 | ms "2.0.0" 75 | 76 | emoji-regex@^8.0.0: 77 | version "8.0.0" 78 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 79 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 80 | 81 | fast-deep-equal@^3.1.1: 82 | version "3.1.3" 83 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 84 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 85 | 86 | ieee754@^1.2.1: 87 | version "1.2.1" 88 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" 89 | integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== 90 | 91 | iota-array@^1.0.0: 92 | version "1.0.0" 93 | resolved "https://registry.yarnpkg.com/iota-array/-/iota-array-1.0.0.tgz#81ef57fe5d05814cd58c2483632a99c30a0e8087" 94 | integrity sha1-ge9X/l0FgUzVjCSDYyqZwwoOgIc= 95 | 96 | is-buffer@^1.0.2: 97 | version "1.1.6" 98 | resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" 99 | integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== 100 | 101 | is-fullwidth-code-point@^3.0.0: 102 | version "3.0.0" 103 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 104 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 105 | 106 | json-schema-traverse@^1.0.0: 107 | version "1.0.0" 108 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" 109 | integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== 110 | 111 | lodash.clonedeep@^4.5.0: 112 | version "4.5.0" 113 | resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" 114 | integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= 115 | 116 | lodash.flatten@^4.4.0: 117 | version "4.4.0" 118 | resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" 119 | integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= 120 | 121 | lodash.truncate@^4.4.2: 122 | version "4.4.2" 123 | resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" 124 | integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= 125 | 126 | ms@2.0.0: 127 | version "2.0.0" 128 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 129 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 130 | 131 | mustache@^4.1.0: 132 | version "4.2.0" 133 | resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64" 134 | integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== 135 | 136 | mutable-buffer@2.0.3: 137 | version "2.0.3" 138 | resolved "https://registry.yarnpkg.com/mutable-buffer/-/mutable-buffer-2.0.3.tgz#67bca5568bf15d3f6035fb716e3899dc44901c8c" 139 | integrity sha1-Z7ylVovxXT9gNftxbjiZ3ESQHIw= 140 | 141 | ndarray@^1.0.19: 142 | version "1.0.19" 143 | resolved "https://registry.yarnpkg.com/ndarray/-/ndarray-1.0.19.tgz#6785b5f5dfa58b83e31ae5b2a058cfd1ab3f694e" 144 | integrity sha512-B4JHA4vdyZU30ELBw3g7/p9bZupyew5a7tX1Y/gGeF2hafrPaQZhgrGQfsvgfYbgdFZjYwuEcnaobeM/WMW+HQ== 145 | dependencies: 146 | iota-array "^1.0.0" 147 | is-buffer "^1.0.2" 148 | 149 | pngjs@^6.0.0: 150 | version "6.0.0" 151 | resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-6.0.0.tgz#ca9e5d2aa48db0228a52c419c3308e87720da821" 152 | integrity sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg== 153 | 154 | punycode@^2.1.0: 155 | version "2.1.1" 156 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 157 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 158 | 159 | require-from-string@^2.0.2: 160 | version "2.0.2" 161 | resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" 162 | integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== 163 | 164 | slice-ansi@^4.0.0: 165 | version "4.0.0" 166 | resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" 167 | integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== 168 | dependencies: 169 | ansi-styles "^4.0.0" 170 | astral-regex "^2.0.0" 171 | is-fullwidth-code-point "^3.0.0" 172 | 173 | string-width@^4.2.0: 174 | version "4.2.2" 175 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" 176 | integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== 177 | dependencies: 178 | emoji-regex "^8.0.0" 179 | is-fullwidth-code-point "^3.0.0" 180 | strip-ansi "^6.0.0" 181 | 182 | strip-ansi@^6.0.0: 183 | version "6.0.0" 184 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" 185 | integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== 186 | dependencies: 187 | ansi-regex "^5.0.0" 188 | 189 | table@^6.6.0: 190 | version "6.6.0" 191 | resolved "https://registry.yarnpkg.com/table/-/table-6.6.0.tgz#905654b79df98d9e9a973de1dd58682532c40e8e" 192 | integrity sha512-iZMtp5tUvcnAdtHpZTWLPF0M7AgiQsURR2DwmxnJwSy8I3+cY+ozzVvYha3BOLG2TB+L0CqjIz+91htuj6yCXg== 193 | dependencies: 194 | ajv "^8.0.1" 195 | lodash.clonedeep "^4.5.0" 196 | lodash.flatten "^4.4.0" 197 | lodash.truncate "^4.4.2" 198 | slice-ansi "^4.0.0" 199 | string-width "^4.2.0" 200 | strip-ansi "^6.0.0" 201 | 202 | typescript@^4.2.4: 203 | version "4.2.4" 204 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.4.tgz#8610b59747de028fda898a8aef0e103f156d0961" 205 | integrity sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg== 206 | 207 | uri-js@^4.2.2: 208 | version "4.4.1" 209 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" 210 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 211 | dependencies: 212 | punycode "^2.1.0" 213 | 214 | xml-parser@^1.2.1: 215 | version "1.2.1" 216 | resolved "https://registry.yarnpkg.com/xml-parser/-/xml-parser-1.2.1.tgz#c31f4c34f2975db82ad013222120592736156fcd" 217 | integrity sha1-wx9MNPKXXbgq0BMiISBZJzYVb80= 218 | dependencies: 219 | debug "^2.2.0" 220 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tillpos/xml-escpos-helper", 3 | "description": "ESC/POS with XML interface", 4 | "keywords": [ 5 | "escpos", 6 | "esc", 7 | "pos", 8 | "xml", 9 | "printer" 10 | ], 11 | "version": "0.3.1", 12 | "files": [ 13 | "lib", 14 | "LICENSE", 15 | "README.md" 16 | ], 17 | "main": "lib/index", 18 | "types": "lib", 19 | "engines": { 20 | "node": ">=4.0.0" 21 | }, 22 | "license": "Apache-2.0", 23 | "scripts": { 24 | "build": "yarn clean && yarn compile", 25 | "build:watch": "yarn compile -- -w", 26 | "clean": "rm -rf ./lib && rm -rf tsconfig.build.tsbuildinfo", 27 | "compile": "tsc -p ./tsconfig.build.json" 28 | }, 29 | "repository": { 30 | "type": "git", 31 | "url": "http://github.com/oolio-group/xml-escpos-helper.git" 32 | }, 33 | "contributors": [ 34 | "Snehit Velma " 35 | ], 36 | "bugs": { 37 | "url": "https://github.com/oolio-group/xml-escpos-helper/issues" 38 | }, 39 | "dependencies": { 40 | "buffer": "^6.0.3", 41 | "mustache": "^4.1.0", 42 | "mutable-buffer": "2.0.3", 43 | "ndarray": "^1.0.19", 44 | "upng-js": "2.1.0", 45 | "xml-parser": "^1.2.1" 46 | }, 47 | "devDependencies": { 48 | "@types/node": "^14.14.20", 49 | "@types/xml-parser": "^1.2.29", 50 | "ts-loader": "^2.3.4", 51 | "tslint": "^5.7.0", 52 | "tslint-eslint-rules": "^4.1.1", 53 | "typescript": "^4.1.3" 54 | } 55 | } -------------------------------------------------------------------------------- /resources/ESCPOS_Command_Manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oolio-group/xml-escpos-helper/a80bd47b56ffe6400d9297c0bb0124300f46bd9a/resources/ESCPOS_Command_Manual.pdf -------------------------------------------------------------------------------- /src/buffer-builder.ts: -------------------------------------------------------------------------------- 1 | import { Command } from "./command"; 2 | import { MutableBuffer } from "mutable-buffer"; 3 | import Image from "./image"; 4 | export class BufferBuilder { 5 | private buffer: MutableBuffer; 6 | private hasGSCommand: boolean; 7 | private doEmphasise: boolean; 8 | 9 | constructor(private defaultSettings: boolean = true) { 10 | this.buffer = new MutableBuffer(); 11 | this.hasGSCommand = true; 12 | this.doEmphasise = false; 13 | 14 | } 15 | 16 | public end(): BufferBuilder { 17 | return this; 18 | } 19 | 20 | public resetCharacterCodeTable(): BufferBuilder { 21 | this.buffer.write(Command.ESC_t(0)); 22 | return this; 23 | } 24 | 25 | public setPrintColor(color: 'black' | 'red' = 'black'): BufferBuilder { 26 | this.buffer.write(Command.ESC_r(color === 'red' ? 1 : 0)); 27 | return this; 28 | } 29 | 30 | public setCharacterSize( 31 | width: number = 0, 32 | height: number = 0 33 | ): BufferBuilder { 34 | if(this.hasGSCommand) 35 | { 36 | let size = (width << 4) + height; 37 | this.buffer.write(Command.GS_exclamation(size)); 38 | } 39 | else{ 40 | let mode = (width>0?(1<<5):0)+(height>0?(1<<4):0)+(this.doEmphasise?(1<<3):0)+1; 41 | this.buffer.write(Command.ESC_exclamation(mode)); 42 | } 43 | 44 | return this; 45 | } 46 | 47 | public setPrintMode(setting:boolean): BufferBuilder { 48 | this.hasGSCommand = setting; 49 | if(setting) this.resetCharacterEncoding(); 50 | this.resetCharacterSize(); 51 | return this; 52 | } 53 | 54 | public resetCharacterSize(): BufferBuilder { 55 | if(this.hasGSCommand) 56 | { 57 | this.buffer.write(Command.GS_exclamation(0)); 58 | } 59 | else 60 | { 61 | this.buffer.write(Command.ESC_exclamation(1)); 62 | } 63 | return this; 64 | } 65 | 66 | public resetCharacterEncoding(): BufferBuilder { 67 | this.buffer.write(Command.FS_ob_C_fe_utf); 68 | return this; 69 | } 70 | 71 | public startCompressedCharacter(): BufferBuilder { 72 | this.buffer.write(Command.ESC_M(1)); 73 | return this; 74 | } 75 | 76 | public endCompressedCharacter(): BufferBuilder { 77 | this.buffer.write(Command.ESC_M(0)); 78 | return this; 79 | } 80 | 81 | public startBold(): BufferBuilder { 82 | this.hasGSCommand? this.buffer.write(Command.ESC_E(1)):this.doEmphasise=true; 83 | return this; 84 | } 85 | 86 | public endBold(): BufferBuilder { 87 | this.hasGSCommand? this.buffer.write(Command.ESC_E(0)):this.doEmphasise=false; 88 | return this; 89 | } 90 | 91 | public startUnderline( 92 | underlineMode: UNDERLINE_MODE = UNDERLINE_MODE.TWO_POINTS_OF_COARSE 93 | ): BufferBuilder { 94 | this.buffer.write(Command.ESC_minus(underlineMode)); 95 | return this; 96 | } 97 | 98 | public endUnderline(): BufferBuilder { 99 | this.buffer.write(Command.ESC_minus(48)); 100 | return this; 101 | } 102 | 103 | public startAlign(alignment: ALIGNMENT): BufferBuilder { 104 | this.buffer.write(Command.ESC_a(alignment)); 105 | return this; 106 | } 107 | 108 | public resetAlign(): BufferBuilder { 109 | return this.startAlign(ALIGNMENT.LEFT); 110 | } 111 | 112 | public startWhiteMode(): BufferBuilder { 113 | this.buffer.write(Command.GS_B(1)); 114 | return this; 115 | } 116 | 117 | public endWhiteMode(): BufferBuilder { 118 | this.buffer.write(Command.GS_B(0)); 119 | return this; 120 | } 121 | 122 | public startReverseMode(): BufferBuilder { 123 | this.buffer.write(Command.ESC_rev(1)); 124 | return this; 125 | } 126 | 127 | public endReverseMode(): BufferBuilder { 128 | this.buffer.write(Command.ESC_rev(0)); 129 | return this; 130 | } 131 | 132 | public printBarcode( 133 | data: string, 134 | barcodeSystem: BARCODE_SYSTEM, 135 | width: BARCODE_WIDTH = BARCODE_WIDTH.DOT_375, 136 | height: number = 162, 137 | labelFont: BARCODE_LABEL_FONT = BARCODE_LABEL_FONT.FONT_A, 138 | labelPosition: BARCODE_LABEL_POSITION = BARCODE_LABEL_POSITION.BOTTOM, 139 | leftSpacing: number = 0 140 | ): BufferBuilder { 141 | this.buffer.write(Command.GS_w(width)); // width 142 | this.buffer.write(Command.GS_h(height)); // height 143 | this.buffer.write(Command.GS_x(leftSpacing)); // left spacing 144 | this.buffer.write(Command.GS_f(labelFont)); // HRI font 145 | this.buffer.write(Command.GS_H(labelPosition)); // HRI font 146 | this.buffer.write(Command.GS_K(barcodeSystem, data.length)); // data is a string in UTF-8 147 | this.buffer.write(data, "ascii"); 148 | return this; 149 | } 150 | 151 | public printQRcode(data: string, model: number, size: number, ecLevel: number): BufferBuilder { 152 | let x = data.length + 3; 153 | let pL = Math.floor(x % 256); 154 | let pH = Math.floor(x / 256); 155 | 156 | this.buffer.write(Command.QR_MODEL(model)); 157 | this.buffer.write(Command.QR_SIZE(size)); 158 | this.buffer.write(Command.EC_LEVEL(ecLevel)); 159 | this.buffer.write(Command.STORE_QR(pL, pH)); 160 | this.buffer.write(data, "ascii"); 161 | this.buffer.write(Command.PRINT_QR()); 162 | 163 | return this; 164 | } 165 | 166 | public printBitmap( 167 | image: number[], 168 | width: number, 169 | height: number, 170 | scale: BITMAP_SCALE = BITMAP_SCALE.NORMAL 171 | ): BufferBuilder { 172 | //TODO 173 | return this; 174 | } 175 | 176 | public printText(text: string): BufferBuilder { 177 | this.buffer.write(text, "utf8"); 178 | return this; 179 | } 180 | 181 | public printTextLine(text: string): BufferBuilder { 182 | return this.printText(text).breakLine(); 183 | } 184 | 185 | public breakLine(lines: number = 0): BufferBuilder { 186 | this.buffer.write(Command.ESC_d(lines)); 187 | return this; 188 | } 189 | 190 | public lineFeed(): BufferBuilder { 191 | this.buffer.write(Command.LF); 192 | return this; 193 | } 194 | 195 | public transmitStatus(statusType: STATUS_TYPE): BufferBuilder { 196 | this.buffer.write(Command.DLE_EOT(statusType)); 197 | return this; 198 | } 199 | 200 | public build(): number[] { 201 | if (this.defaultSettings) { 202 | this.lineFeed(); 203 | this.buffer.write(Command.ESC_init); 204 | } 205 | 206 | return this.buffer.flush(); 207 | } 208 | 209 | /** 210 | * Register Paper Cut Action 211 | * @return BufferBuilder 212 | */ 213 | public paperCut(): BufferBuilder { 214 | this.buffer.write(Command.GS_v(66,50)); 215 | return this; 216 | } 217 | 218 | /** 219 | * Register open cash drawer action 220 | * @return BufferBuilder 221 | */ 222 | public openCashDrawer(): BufferBuilder { 223 | // kick drawer 1, pin 2 224 | this.buffer.write(Command.CD_KICK_1()); 225 | // kick drawer 2, pin 5 226 | this.buffer.write(Command.CD_KICK_2()); 227 | return this; 228 | } 229 | 230 | public printImage(image: Image, mode: RASTER_MODE): BufferBuilder { 231 | if (!(image instanceof Image)) { 232 | throw new TypeError("not supported"); 233 | } 234 | const raster = image.toRaster(); 235 | this.buffer.write(Command.GS_v0(mode)); 236 | this.buffer.writeUInt16LE(raster.width); 237 | this.buffer.writeUInt16LE(raster.height); 238 | this.buffer.write(raster.data); 239 | return this; 240 | } 241 | } 242 | 243 | export enum UNDERLINE_MODE { 244 | ONE_POINT_OF_COARSE = 49, 245 | TWO_POINTS_OF_COARSE = 50, 246 | } 247 | 248 | export enum ALIGNMENT { 249 | LEFT = 48, 250 | CENTER = 49, 251 | RIGHT = 50, 252 | } 253 | 254 | export enum BARCODE_SYSTEM { 255 | UPC_A = 65, 256 | UPC_E = 66, 257 | EAN_13 = 67, 258 | EAN_8 = 68, 259 | CODE_39 = 69, 260 | ITF = 70, 261 | CODABAR = 71, 262 | CODE_93 = 72, 263 | CODE_128 = 73, 264 | } 265 | 266 | export enum BARCODE_WIDTH { 267 | DOT_250 = 2, 268 | DOT_375 = 3, 269 | DOT_560 = 4, 270 | DOT_625 = 5, 271 | DOT_750 = 6, 272 | } 273 | 274 | export enum BARCODE_LABEL_FONT { 275 | FONT_A = 48, 276 | FONT_B = 49, 277 | } 278 | 279 | export enum BARCODE_LABEL_POSITION { 280 | NOT_PRINT = 48, 281 | ABOVE = 49, 282 | BOTTOM = 50, 283 | ABOVE_BOTTOM = 51, 284 | } 285 | 286 | export enum QR_EC_LEVEL { 287 | L = 0, 288 | M = 1, 289 | Q = 2, 290 | H = 3, 291 | } 292 | 293 | export enum BITMAP_SCALE { 294 | NORMAL = 48, 295 | DOUBLE_WIDTH = 49, 296 | DOUBLE_HEIGHT = 50, 297 | FOUR_TIMES = 51, 298 | } 299 | 300 | export enum STATUS_TYPE { 301 | PRINTER_STATUS = 1, 302 | OFFLINE_STATUS = 2, 303 | ERROR_STATUS = 3, 304 | PAPER_ROLL_SENSOR_STATUS = 4, 305 | } 306 | 307 | export enum RASTER_MODE { 308 | NORMAL = 0, 309 | DOUBLE_WIDTH = 1, 310 | DOUBLE_HEIGHT = 2, 311 | DOUBLE_WIDTH_HEIGHT = 3, 312 | } 313 | -------------------------------------------------------------------------------- /src/command.ts: -------------------------------------------------------------------------------- 1 | export class Command { 2 | 3 | public static ESC: number = 0x1B; 4 | public static FF: number = 0x0C; 5 | public static FS: number = 0x1C; 6 | public static GS: number = 0x1D; 7 | public static DC1: number = 0x11; 8 | public static DC4: number = 0x14; 9 | public static DLE: number = 0x10; 10 | public static NL: number = 0x0A; 11 | public static SP: number = 0x20; 12 | public static US: number = 0x1F; 13 | 14 | public static DLE_EOT = (n: number): number[] => [Command.DLE, 0x04, n]; // DLEEOTn 15 | 16 | public static ESC_init: number[] = [Command.ESC, 0x40]; //ESC@ 17 | public static ESC_exclamation = (n: number): number[] => [Command.ESC, 0x21, n]; // ESC!n 18 | public static ESC_minus = (n: number): number[] => [Command.ESC, 0x2D, n]; // ESC-n 19 | public static ESC_rev = (n: number): number[] => [Command.ESC, 0x7B, n]; // ESC{n 20 | public static ESC_a = (n: number): number[] => [Command.ESC, 0x61, n]; // ESCan 21 | public static ESC_d = (n: number): number[] => [Command.ESC, 0x64, n]; // ESCdn 22 | public static ESC_E = (n: number): number[] => [Command.ESC, 0x45, n]; // ESCEn 23 | public static ESC_G = (n: number): number[] => [Command.ESC, 0x47, n]; // ESCGn 24 | public static ESC_J = (n: number): number[] => [Command.ESC, 0x4A, n]; // ESCJn 25 | public static ESC_M = (n: number): number[] => [Command.ESC, 0x4D, n]; // ESCMn 26 | public static ESC_t = (n: number): number[] => [Command.ESC, 0x07, n]; // ESCtn 27 | public static ESC_Z = (m: number, n: number, k: number): number[] => [Command.ESC, 0x5A, m, n, k]; // ESCZmnk 28 | public static ESC_r = (n: number): number[] => [Command.ESC, 0x72, n]; // ESCR 29 | 30 | 31 | public static FS_and: number[] = [Command.FS, 0x40]; //ESC@ 32 | public static FS_ob_C_fe_utf = [Command.FS, 0x28, 0x43, 0x02, 0x00, 0x30, 0x02]; //UTF-8 encoding 33 | 34 | public static GS_exclamation = (n: number): number[] => [Command.GS, 0x21, n]; // ESC!n 35 | public static GS_B = (n: number): number[] => [Command.GS, 0x42, n]; // GSBn 36 | public static GS_f = (n: number): number[] => [Command.GS, 0x66, n]; // GSfn 37 | public static GS_h = (n: number): number[] => [Command.GS, 0x68, n]; // GShn 38 | public static GS_H = (n: number): number[] => [Command.GS, 0x48, n]; // GSHn 39 | public static GS_K = (m: number, n: number): number[] => [Command.GS, 0x6B, m, n]; // GSKmn 40 | public static GS_v0 = (m: number): number[] => [Command.GS, 0x76, 0x30, m]; // GSv0m 41 | public static GS_w = (n: number): number[] => [Command.GS, 0x77, n]; // GSwn 42 | public static GS_x = (n: number): number[] => [Command.GS, 0x78, n]; // GSxn 43 | public static GS_v = (m: number, n: number): number[] => [Command.GS, 0x56, m, n]; // GSv 44 | public static ESC_ak = (n: number): number[] => [Command.ESC, 0x2A, n]; // ESC*n 45 | public static ESC_akp = (m: number, nL: number,nH: number ): number[] => [Command.ESC, 0x2A, m, nL, nH]; // ESC*n 46 | 47 | public static LF: number[] = [Command.NL]; 48 | 49 | 50 | // Cash Drawer 51 | public static CD_KICK_1 = (): number[] => [Command.ESC, 0x70, 0x00]; // Sends a pulse to pin 2 52 | public static CD_KICK_2 = (): number[] => [Command.ESC, 0x70, 0x01]; // Sends a pulse to pin 5 53 | 54 | //QR Code 55 | public static QR_MODEL =(n: number): number[]=> [29, 40, 107, 4, 0, 49, 65, n, 0]; //Select QR model, n = 49/50 56 | //[29 40 107 4 0 49 65 n1 n2] 57 | public static QR_SIZE =(n: number): number[] => [29, 40, 107, 3, 0, 49, 67, n]; //Set QR size, n = 8? 58 | //[29 40 107 3 0 49 67 n] 59 | public static EC_LEVEL =(n: number): number[] => [29, 40, 107, 3, 0, 49, 69, n]; //Set error correction level for QR, n = 48/49/50/51 60 | //[29 40 107 3 0 49 69 n] 61 | public static STORE_QR =(pL, pH): number[] => [29, 40, 107, pL, pH, 49, 80, 48]; //Store QR data in symbol storage area 62 | //[29 40 107 pL pH 49 80 48 d1…dk] 63 | public static PRINT_QR =(): number[] => [29, 40, 107, 3, 0, 49, 81, 48]; //Print QR from data in symbol storage area 64 | //[29 40 107 3 0 49 81 m] 65 | } 66 | -------------------------------------------------------------------------------- /src/escpos.ts: -------------------------------------------------------------------------------- 1 | import { TemplateParser } from './template-parser'; 2 | import { XMLParser } from './xml-parser'; 3 | import { BufferBuilder } from './buffer-builder'; 4 | 5 | export class EscPos { 6 | 7 | public static getBufferFromTemplate(template: string, data: any): number[] { 8 | let templateParser = new TemplateParser(); 9 | return templateParser.parser(template, data).build(); 10 | } 11 | 12 | public static getBufferFromXML(xml: string): number[] { 13 | let xmlParser = new XMLParser(); 14 | return xmlParser.parser(xml).build(); 15 | } 16 | 17 | public static getBufferBuilder(): BufferBuilder { 18 | return new BufferBuilder(); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/image.ts: -------------------------------------------------------------------------------- 1 | class Image { 2 | public pixels; 3 | public data; 4 | constructor(pixels) { 5 | this.pixels = pixels; 6 | 7 | this.data = []; 8 | function rgb(pixel) { 9 | return { 10 | r: pixel[0], 11 | g: pixel[1], 12 | b: pixel[2], 13 | a: pixel[3], 14 | }; 15 | } 16 | 17 | var self = this; 18 | for (var i = 0; i < this.pixels.data.length; i += this.size.colors) { 19 | this.data.push( 20 | rgb( 21 | new Array(this.size.colors).fill(0).map(function (_, b) { 22 | return self.pixels.data[i + b]; 23 | }) 24 | ) 25 | ); 26 | } 27 | 28 | this.data = this.data.map(function (pixel) { 29 | if (pixel.a == 0) return 0; 30 | var shouldBeWhite = pixel.r > 200 && pixel.g > 200 && pixel.b > 200; 31 | return shouldBeWhite ? 0 : 1; 32 | }); 33 | } 34 | 35 | /** 36 | * [description] 37 | * @return {[type]} [description] 38 | */ 39 | get size() { 40 | return { 41 | width: this.pixels.shape[0], 42 | height: this.pixels.shape[1], 43 | colors: this.pixels.shape[2], 44 | }; 45 | } 46 | 47 | /** 48 | * [toBitmap description] 49 | * @param {[type]} density [description] 50 | * @return {[type]} [description] 51 | */ 52 | public toBitmap(density) { 53 | density = density || 24; 54 | 55 | var ld, 56 | result = []; 57 | var x, y, b, l, i; 58 | var c = density / 8; 59 | 60 | // n blocks of lines 61 | var n = Math.ceil(this.size.height / density); 62 | 63 | for (y = 0; y < n; y++) { 64 | // line data 65 | ld = result[y] = []; 66 | 67 | for (x = 0; x < this.size.width; x++) { 68 | for (b = 0; b < density; b++) { 69 | i = x * c + (b >> 3); 70 | 71 | if (ld[i] === undefined) { 72 | ld[i] = 0; 73 | } 74 | 75 | l = y * density + b; 76 | if (l < this.size.height) { 77 | if (this.data[l * this.size.width + x]) { 78 | ld[i] += 0x80 >> (b & 0x7); 79 | } 80 | } 81 | } 82 | } 83 | } 84 | 85 | return { 86 | data: result, 87 | density: density, 88 | }; 89 | } 90 | 91 | /** 92 | * [toRaster description] 93 | * @return {[type]} [description] 94 | */ 95 | public toRaster() { 96 | var result = []; 97 | var width = this.size.width; 98 | var height = this.size.height; 99 | var data = this.data; 100 | 101 | // n blocks of lines 102 | var n = Math.ceil(width / 8); 103 | var x, y, b, c, i; 104 | 105 | for (y = 0; y < height; y++) { 106 | for (x = 0; x < n; x++) { 107 | for (b = 0; b < 8; b++) { 108 | i = x * 8 + b; 109 | 110 | if (result[y * n + x] === undefined) { 111 | result[y * n + x] = 0; 112 | } 113 | 114 | c = x * 8 + b; 115 | if (c < width) { 116 | if (data[y * width + i]) { 117 | result[y * n + x] += 0x80 >> (b & 0x7); 118 | } 119 | } 120 | } 121 | } 122 | } 123 | return { 124 | data: result, 125 | width: n, 126 | height: height, 127 | }; 128 | } 129 | } 130 | 131 | export default Image; 132 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | global.Buffer = global.Buffer || require('buffer').Buffer; 2 | export * from './template-parser'; 3 | export * from './xml-parser'; 4 | export * from './buffer-builder'; 5 | export * from './escpos'; 6 | -------------------------------------------------------------------------------- /src/node-factory.ts: -------------------------------------------------------------------------------- 1 | import AlignNode from './nodes/align-node'; 2 | import BarcodeNode from './nodes/barcode-node'; 3 | import BoldNode from './nodes/bold-node'; 4 | import BreakLineNode from './nodes/break-line-node'; 5 | import DocumentNode from './nodes/document-node'; 6 | import LineFeedNode from './nodes/line-feed-node'; 7 | import QRcodeNode from './nodes/qrcode-node'; 8 | import SmallNode from './nodes/small-node'; 9 | import TextNode from './nodes/text-node'; 10 | import TextLineNode from './nodes/text-line-node'; 11 | import UnderlineNode from './nodes/underline-node'; 12 | import WhiteModeNode from './nodes/white-mode-node'; 13 | import PaperCutNode from './nodes/paper-cut-node'; 14 | import ImageNode from './nodes/image-node'; 15 | import OpenCashDrawerNode from './nodes/open-cash-drawer-node'; 16 | import PrintModeNode from './nodes/print-mode'; 17 | 18 | export class NodeFactory { 19 | 20 | public static create(nodeType: String, node) { 21 | switch (nodeType) { 22 | case 'align': return new AlignNode(node); 23 | case 'barcode': return new BarcodeNode(node); 24 | case 'bold': return new BoldNode(node); 25 | case 'break-line': return new BreakLineNode(node); 26 | case 'document': return new DocumentNode(node); 27 | case 'line-feed': return new LineFeedNode(node); 28 | case 'qrcode': return new QRcodeNode(node); 29 | case 'small': return new SmallNode(node); 30 | case 'text': return new TextNode(node); 31 | case 'text-line': return new TextLineNode(node); 32 | case 'underline': return new UnderlineNode(node); 33 | case 'white-mode': return new WhiteModeNode(node); 34 | case 'paper-cut': return new PaperCutNode(node); 35 | case 'open-cash-drawer': return new OpenCashDrawerNode(node); 36 | case 'image': return new ImageNode(node); 37 | case 'print-mode': return new PrintModeNode(node); 38 | 39 | default: return null; 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/nodes/align-node.ts: -------------------------------------------------------------------------------- 1 | import { XMLNode } from '../xml-node'; 2 | import { BufferBuilder, ALIGNMENT } from '../buffer-builder'; 3 | 4 | export default class AlignNode extends XMLNode { 5 | 6 | constructor(node: any) { 7 | super(node); 8 | } 9 | 10 | public open(bufferBuilder: BufferBuilder): BufferBuilder { 11 | switch (this.attributes.mode) { 12 | case 'center': 13 | bufferBuilder.startAlign(ALIGNMENT.CENTER); break; 14 | case 'left': 15 | bufferBuilder.startAlign(ALIGNMENT.LEFT); break; 16 | case 'right': 17 | bufferBuilder.startAlign(ALIGNMENT.RIGHT); break; 18 | } 19 | return bufferBuilder; 20 | } 21 | 22 | public close(bufferBuilder: BufferBuilder): BufferBuilder { 23 | bufferBuilder.resetAlign(); 24 | return bufferBuilder; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/nodes/barcode-node.ts: -------------------------------------------------------------------------------- 1 | import { XMLNode } from '../xml-node'; 2 | import { BufferBuilder, BARCODE_SYSTEM, BARCODE_WIDTH, BARCODE_LABEL_FONT, BARCODE_LABEL_POSITION } from '../buffer-builder'; 3 | 4 | export default class BarcodeNode extends XMLNode { 5 | 6 | constructor(node: any) { 7 | super(node); 8 | } 9 | 10 | public open(bufferBuilder: BufferBuilder): BufferBuilder { 11 | let system, width, height, labelFont, labelPosition, leftSpacing; 12 | 13 | switch (this.attributes.system) { 14 | case 'UPC_A': 15 | system = BARCODE_SYSTEM.UPC_A; break; 16 | case 'UPC_E': 17 | system = BARCODE_SYSTEM.UPC_E; break; 18 | case 'EAN_13': 19 | system = BARCODE_SYSTEM.EAN_13; break; 20 | case 'EAN_8': 21 | system = BARCODE_SYSTEM.EAN_8; break; 22 | case 'CODE_39': 23 | system = BARCODE_SYSTEM.CODE_39; break; 24 | case 'ITF': 25 | system = BARCODE_SYSTEM.ITF; break; 26 | case 'CODABAR': 27 | system = BARCODE_SYSTEM.CODABAR; break; 28 | case 'CODE_93': 29 | system = BARCODE_SYSTEM.CODE_93; break; 30 | case 'CODE_128': 31 | system = BARCODE_SYSTEM.CODE_128; break; 32 | } 33 | 34 | switch (this.attributes.width) { 35 | case 'DOT_250': 36 | width = BARCODE_WIDTH.DOT_250; break; 37 | case 'DOT_375': 38 | width = BARCODE_WIDTH.DOT_375; break; 39 | case 'DOT_560': 40 | width = BARCODE_WIDTH.DOT_560; break; 41 | case 'DOT_625': 42 | width = BARCODE_WIDTH.DOT_625; break; 43 | case 'DOT_750': 44 | width = BARCODE_WIDTH.DOT_750; break; 45 | default: 46 | width = BARCODE_WIDTH.DOT_375; 47 | } 48 | 49 | switch (this.attributes.labelFont) { 50 | case 'FONT_A': 51 | labelFont = BARCODE_LABEL_FONT.FONT_A; break; 52 | case 'FONT_B': 53 | labelFont = BARCODE_LABEL_FONT.FONT_B; break; 54 | default: 55 | labelFont = BARCODE_LABEL_FONT.FONT_A; 56 | } 57 | 58 | switch (this.attributes.labelPosition) { 59 | case 'NOT_PRINT': 60 | labelPosition = BARCODE_LABEL_POSITION.NOT_PRINT; break; 61 | case 'ABOVE': 62 | labelPosition = BARCODE_LABEL_POSITION.ABOVE; break; 63 | case 'BOTTOM': 64 | labelPosition = BARCODE_LABEL_POSITION.BOTTOM; break; 65 | case 'ABOVE_BOTTOM': 66 | labelPosition = BARCODE_LABEL_POSITION.ABOVE_BOTTOM; break; 67 | default: 68 | labelPosition = BARCODE_LABEL_POSITION.BOTTOM; 69 | } 70 | 71 | if (/\d+/.test(this.attributes.height)) { 72 | height = parseInt(this.attributes.height); 73 | } else { 74 | height = 162; 75 | } 76 | 77 | if (/\d+/.test(this.attributes.leftSpacing)) { 78 | leftSpacing = parseInt(this.attributes.leftSpacing); 79 | } else { 80 | leftSpacing = 0; 81 | } 82 | 83 | if (system && this.content) { 84 | bufferBuilder.printBarcode(this.content, system, width, height, labelFont, labelPosition, leftSpacing); 85 | } 86 | 87 | return bufferBuilder; 88 | } 89 | 90 | public close(bufferBuilder: BufferBuilder): BufferBuilder { 91 | return bufferBuilder; 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/nodes/bold-node.ts: -------------------------------------------------------------------------------- 1 | import { XMLNode } from '../xml-node'; 2 | import { BufferBuilder } from '../buffer-builder'; 3 | 4 | export default class BoldNode extends XMLNode { 5 | 6 | constructor(node: any) { 7 | super(node); 8 | } 9 | 10 | public open(bufferBuilder: BufferBuilder): BufferBuilder { 11 | bufferBuilder.startBold(); 12 | return bufferBuilder; 13 | } 14 | 15 | public close(bufferBuilder: BufferBuilder): BufferBuilder { 16 | bufferBuilder.endBold(); 17 | return bufferBuilder; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/nodes/break-line-node.ts: -------------------------------------------------------------------------------- 1 | import { XMLNode } from '../xml-node'; 2 | import { BufferBuilder } from '../buffer-builder'; 3 | 4 | export default class BreakLineNode extends XMLNode { 5 | 6 | constructor(node: any) { 7 | super(node); 8 | } 9 | 10 | public open(bufferBuilder: BufferBuilder): BufferBuilder { 11 | let lines: number = 0; 12 | if (/\d+/.test(this.attributes.lines)) 13 | lines = parseInt(this.attributes.lines) - 1; 14 | 15 | return bufferBuilder.breakLine(lines); 16 | } 17 | 18 | public close(bufferBuilder: BufferBuilder): BufferBuilder { 19 | return bufferBuilder; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/nodes/document-node.ts: -------------------------------------------------------------------------------- 1 | import { XMLNode } from '../xml-node'; 2 | import { BufferBuilder } from '../buffer-builder'; 3 | 4 | export default class DocumentNode extends XMLNode { 5 | 6 | constructor(node: any) { 7 | super(node); 8 | } 9 | 10 | public open(bufferBuilder: BufferBuilder): BufferBuilder { 11 | if (this.attributes.reverse) 12 | bufferBuilder.startReverseMode(); 13 | 14 | return bufferBuilder; 15 | } 16 | 17 | public close(bufferBuilder: BufferBuilder): BufferBuilder { 18 | bufferBuilder.endReverseMode(); 19 | return bufferBuilder; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/nodes/image-node.ts: -------------------------------------------------------------------------------- 1 | import { XMLNode } from '../xml-node'; 2 | import { BufferBuilder, RASTER_MODE } from '../buffer-builder'; 3 | import ndarray from 'ndarray'; 4 | import Image from '../image'; 5 | import upngjs from 'upng-js'; 6 | 7 | export default class ImageNode extends XMLNode { 8 | constructor(node: any) { 9 | super(node); 10 | } 11 | 12 | public open(bufferBuilder: BufferBuilder): BufferBuilder { 13 | const img_data = upngjs.decode( 14 | Buffer.from(this.content.replace(///g, '/'), 'base64'), 15 | ); 16 | 17 | const pixels = ndarray( 18 | new Uint8Array(img_data.data), 19 | [img_data.width | 0, img_data.height | 0, 4], 20 | [4, (4 * img_data.width) | 0, 1], 21 | 0, 22 | ); 23 | 24 | let mode; 25 | switch (this.attributes.mode) { 26 | case 'NORMAL': 27 | mode = RASTER_MODE.NORMAL; 28 | break; 29 | case 'DW': 30 | mode = RASTER_MODE.DOUBLE_WIDTH; 31 | break; 32 | case 'DH': 33 | mode = RASTER_MODE.DOUBLE_HEIGHT; 34 | break; 35 | case 'DWH': 36 | mode = RASTER_MODE.DOUBLE_WIDTH_HEIGHT; 37 | break; 38 | default: 39 | mode = RASTER_MODE.NORMAL; 40 | } 41 | 42 | bufferBuilder.printImage(new Image(pixels), mode); 43 | return bufferBuilder; 44 | } 45 | 46 | public close(bufferBuilder: BufferBuilder): BufferBuilder { 47 | return bufferBuilder; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/nodes/line-feed-node.ts: -------------------------------------------------------------------------------- 1 | import { XMLNode } from '../xml-node'; 2 | import { BufferBuilder } from '../buffer-builder'; 3 | 4 | export default class LineFeedNode extends XMLNode { 5 | 6 | constructor(node: any) { 7 | super(node); 8 | } 9 | 10 | public open(bufferBuilder: BufferBuilder): BufferBuilder { 11 | return bufferBuilder.lineFeed(); 12 | } 13 | 14 | public close(bufferBuilder: BufferBuilder): BufferBuilder { 15 | return bufferBuilder; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/nodes/open-cash-drawer-node.ts: -------------------------------------------------------------------------------- 1 | import { XMLNode } from '../xml-node'; 2 | import { BufferBuilder } from '../buffer-builder'; 3 | 4 | export default class OpenCashDrawerNode extends XMLNode { 5 | 6 | constructor(node: any) { 7 | super(node); 8 | } 9 | 10 | public open(bufferBuilder: BufferBuilder): BufferBuilder { 11 | return bufferBuilder.openCashDrawer(); 12 | } 13 | 14 | public close(bufferBuilder: BufferBuilder): BufferBuilder { 15 | return bufferBuilder; 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /src/nodes/paper-cut-node.ts: -------------------------------------------------------------------------------- 1 | import { XMLNode } from '../xml-node'; 2 | import { BufferBuilder } from '../buffer-builder'; 3 | 4 | export default class PaperCutNode extends XMLNode { 5 | 6 | constructor(node: any) { 7 | super(node); 8 | } 9 | 10 | public open(bufferBuilder: BufferBuilder): BufferBuilder { 11 | return bufferBuilder.paperCut(); 12 | } 13 | 14 | public close(bufferBuilder: BufferBuilder): BufferBuilder { 15 | return bufferBuilder; 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /src/nodes/print-mode.ts: -------------------------------------------------------------------------------- 1 | import { XMLNode } from '../xml-node'; 2 | import { BufferBuilder } from '../buffer-builder'; 3 | 4 | export default class PrintModeNode extends XMLNode { 5 | 6 | constructor(node: any) { 7 | super(node); 8 | } 9 | 10 | public open(bufferBuilder: BufferBuilder): BufferBuilder { 11 | if(this.attributes.mode === 'U220') 12 | { 13 | bufferBuilder.setPrintMode(false); 14 | } 15 | else 16 | { 17 | bufferBuilder.setPrintMode(true); 18 | } 19 | return bufferBuilder; 20 | } 21 | 22 | public close(bufferBuilder: BufferBuilder): BufferBuilder { 23 | bufferBuilder.resetAlign(); 24 | return bufferBuilder; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/nodes/qrcode-node.ts: -------------------------------------------------------------------------------- 1 | import { XMLNode } from '../xml-node'; 2 | import { BufferBuilder, QR_EC_LEVEL } from '../buffer-builder'; 3 | 4 | export default class QRcodeNode extends XMLNode { 5 | 6 | constructor(node: any) { 7 | super(node); 8 | } 9 | 10 | public open(bufferBuilder: BufferBuilder): BufferBuilder { 11 | let qrModel, qrSize, ecLevel; 12 | 13 | switch (this.attributes.model) { 14 | case '1': 15 | qrModel = 49; break; 16 | case '2': 17 | qrModel = 50; break; 18 | default: 19 | qrModel = 50; 20 | } 21 | 22 | if (/\d+/.test(this.attributes.size)) { 23 | qrSize = parseInt(this.attributes.size); 24 | } 25 | else { 26 | qrSize = 8; 27 | } 28 | 29 | switch (this.attributes.ecl) { 30 | case 'L': 31 | ecLevel = 48; break; 32 | case 'M': 33 | ecLevel = 49; break; 34 | case 'Q': 35 | ecLevel = 50; break; 36 | case 'H': 37 | ecLevel = 51; break; 38 | default: 39 | ecLevel = 48; 40 | } 41 | 42 | if (this.content) { 43 | let url = this.content.replace(/ /g, ' ').replace(/&/g, '&').replace(/=/g, '=').replace(///g, '/').replace(/</g, '<').replace(/>/g, '>').replace(/'/g, "'").replace(/"/g, '"') 44 | bufferBuilder.printQRcode(url, qrModel, qrSize, ecLevel); 45 | } 46 | 47 | return bufferBuilder; 48 | } 49 | 50 | public close(bufferBuilder: BufferBuilder): BufferBuilder { 51 | return bufferBuilder; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/nodes/small-node.ts: -------------------------------------------------------------------------------- 1 | import { XMLNode } from '../xml-node'; 2 | import { BufferBuilder } from '../buffer-builder'; 3 | 4 | export default class SmallNode extends XMLNode { 5 | 6 | constructor(node: any) { 7 | super(node); 8 | } 9 | 10 | public open(bufferBuilder: BufferBuilder): BufferBuilder { 11 | bufferBuilder.startCompressedCharacter(); 12 | return bufferBuilder; 13 | } 14 | 15 | public close(bufferBuilder: BufferBuilder): BufferBuilder { 16 | bufferBuilder.endCompressedCharacter(); 17 | return bufferBuilder; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/nodes/text-line-node.ts: -------------------------------------------------------------------------------- 1 | import { XMLNode } from '../xml-node'; 2 | import { BufferBuilder } from '../buffer-builder'; 3 | import TextNode from './text-node'; 4 | 5 | export default class TextLineNode extends XMLNode { 6 | 7 | private textNode: TextNode; 8 | 9 | constructor(node: any) { 10 | super(node); 11 | this.textNode = new TextNode(node); 12 | } 13 | 14 | public open(bufferBuilder: BufferBuilder): BufferBuilder { 15 | return this.textNode.open(bufferBuilder); 16 | } 17 | 18 | public close(bufferBuilder: BufferBuilder): BufferBuilder { 19 | return this.textNode.close(bufferBuilder).breakLine(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/nodes/text-node.ts: -------------------------------------------------------------------------------- 1 | import { XMLNode } from '../xml-node'; 2 | import { BufferBuilder } from '../buffer-builder'; 3 | 4 | export default class TextNode extends XMLNode { 5 | 6 | constructor(node: any) { 7 | super(node); 8 | } 9 | 10 | public open(bufferBuilder: BufferBuilder): BufferBuilder { 11 | 12 | if (/\d+:\d+/.test(this.attributes.size)) { 13 | let size: number[] = new String(this.attributes.size).split(':').map(entry => parseInt(entry)); 14 | bufferBuilder.setCharacterSize(size[0], size[1]); 15 | } 16 | 17 | bufferBuilder.setPrintColor(this.attributes.color); 18 | 19 | let text = this.getContent().replace(/ /g, ' ').replace(/<tab>/g, ' ').replace(/&/g, '&').replace(/=/g, '=').replace(///g, '/').replace(/</g, '<').replace(/>/g, '>').replace(/'/g, "'").replace(/"/g, '"'); 20 | 21 | bufferBuilder.printText(text); 22 | return bufferBuilder; 23 | } 24 | 25 | public close(bufferBuilder: BufferBuilder): BufferBuilder { 26 | bufferBuilder.resetCharacterSize(); 27 | return bufferBuilder; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/nodes/underline-node.ts: -------------------------------------------------------------------------------- 1 | import { XMLNode } from '../xml-node'; 2 | import { BufferBuilder, UNDERLINE_MODE } from '../buffer-builder'; 3 | 4 | export default class UnderlineNode extends XMLNode { 5 | 6 | constructor(node: any) { 7 | super(node); 8 | } 9 | 10 | public open(bufferBuilder: BufferBuilder): BufferBuilder { 11 | switch (this.attributes.mode) { 12 | case 'one-point': 13 | bufferBuilder.startUnderline(UNDERLINE_MODE.ONE_POINT_OF_COARSE); break; 14 | case 'two-points': 15 | bufferBuilder.startUnderline(UNDERLINE_MODE.TWO_POINTS_OF_COARSE); break; 16 | default: 17 | bufferBuilder.startUnderline(); 18 | } 19 | return bufferBuilder; 20 | } 21 | 22 | public close(bufferBuilder: BufferBuilder): BufferBuilder { 23 | bufferBuilder.endUnderline(); 24 | return bufferBuilder; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/nodes/white-mode-node.ts: -------------------------------------------------------------------------------- 1 | import { XMLNode } from '../xml-node'; 2 | import { BufferBuilder } from '../buffer-builder'; 3 | 4 | export default class WhiteModeNode extends XMLNode { 5 | 6 | constructor(node: any) { 7 | super(node); 8 | } 9 | 10 | public open(bufferBuilder: BufferBuilder): BufferBuilder { 11 | bufferBuilder.startWhiteMode(); 12 | return bufferBuilder; 13 | } 14 | 15 | public close(bufferBuilder: BufferBuilder): BufferBuilder { 16 | bufferBuilder.endWhiteMode(); 17 | return bufferBuilder; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/template-parser.ts: -------------------------------------------------------------------------------- 1 | import Mustache from 'mustache'; 2 | import { XMLParser } from './xml-parser'; 3 | import { BufferBuilder } from './buffer-builder'; 4 | 5 | export class TemplateParser { 6 | private mustache: any; 7 | 8 | constructor() { 9 | this.mustache = Mustache; 10 | } 11 | 12 | public parser(template, scope): BufferBuilder { 13 | const xml = this.mustache.render(template, scope); 14 | return new XMLParser().parser(xml); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/xml-node.ts: -------------------------------------------------------------------------------- 1 | import { BufferBuilder } from './buffer-builder'; 2 | 3 | export abstract class XMLNode { 4 | 5 | protected attributes: any; 6 | protected content: string; 7 | protected children: XMLNode[]; 8 | 9 | constructor(node: any) { 10 | this.attributes = node.attributes || {}; 11 | this.content = node.content; 12 | this.children = []; 13 | } 14 | 15 | public addChild(child: XMLNode) { 16 | if (child) 17 | this.children.push(child); 18 | } 19 | 20 | protected getContent(): string { 21 | return this.content; 22 | } 23 | 24 | public abstract open(bufferBuilder: BufferBuilder): BufferBuilder | Promise; 25 | 26 | public abstract close(bufferBuilder: BufferBuilder): BufferBuilder; 27 | 28 | public draw(bufferBuilder: BufferBuilder): BufferBuilder { 29 | 30 | // open tag 31 | this.open(bufferBuilder); 32 | 33 | if (this.children.length > 0) { 34 | this.children.forEach(child => child.draw(bufferBuilder)); 35 | } 36 | 37 | // close tag 38 | this.close(bufferBuilder); 39 | 40 | return bufferBuilder; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/xml-parser.ts: -------------------------------------------------------------------------------- 1 | import parser from 'xml-parser'; 2 | import { BufferBuilder } from './buffer-builder'; 3 | import { XMLNode } from './xml-node'; 4 | import { NodeFactory } from './node-factory'; 5 | 6 | export class XMLParser { 7 | 8 | public parser(xml: string): BufferBuilder { 9 | let parsedXML = parser(xml); 10 | return this.compile(parsedXML); 11 | } 12 | 13 | private compile(parsedXML: any): BufferBuilder { 14 | let bufferBuilder = new BufferBuilder(); 15 | let rootNode = this.adapter(parsedXML.root, null); 16 | return rootNode.draw(bufferBuilder); 17 | } 18 | 19 | private adapter(node: any, parentNode): XMLNode { 20 | let xmlNode: XMLNode = NodeFactory.create(node.name, node); 21 | if (parentNode) parentNode.addChild(xmlNode); 22 | if (node.children.length > 0) { 23 | node.children.forEach(child => { 24 | this.adapter(child, xmlNode); 25 | }); 26 | } 27 | return xmlNode; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "ES2019", 5 | "outDir": "lib", 6 | "declaration": true, 7 | "esModuleInterop": true, 8 | "moduleResolution": "node", 9 | "emitDecoratorMetadata": true, 10 | "experimentalDecorators": true, 11 | "resolveJsonModule": true, 12 | "skipLibCheck": true 13 | }, 14 | 15 | "exclude": ["node_modules", "dist", "examples"] 16 | } 17 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.build.json", 3 | 4 | "compilerOptions": { 5 | "baseUrl": ".", 6 | "esModuleInterop": true, 7 | "resolveJsonModule": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-duplicate-variable": true, 4 | "no-unused-variable": [ 5 | true 6 | ] 7 | }, 8 | "rulesDirectory": [ 9 | "node_modules/tslint-eslint-rules/dist/rules" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@^7.0.0": 6 | version "7.12.11" 7 | resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz" 8 | integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== 9 | dependencies: 10 | "@babel/highlight" "^7.10.4" 11 | 12 | "@babel/helper-validator-identifier@^7.10.4": 13 | version "7.12.11" 14 | resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz" 15 | integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== 16 | 17 | "@babel/highlight@^7.10.4": 18 | version "7.10.4" 19 | resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz" 20 | integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== 21 | dependencies: 22 | "@babel/helper-validator-identifier" "^7.10.4" 23 | chalk "^2.0.0" 24 | js-tokens "^4.0.0" 25 | 26 | "@types/node@^14.14.20": 27 | version "14.14.20" 28 | resolved "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz" 29 | integrity sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A== 30 | 31 | "@types/xml-parser@^1.2.29": 32 | version "1.2.29" 33 | resolved "https://registry.npmjs.org/@types/xml-parser/-/xml-parser-1.2.29.tgz" 34 | integrity sha512-l5ID65aPDctN/dZYkDgLOEBuoHrD8S9TyfD5soORUtVHKyOs7Wr66iNxAtcmT/tER1GeYqp51jR6l08gmsRcZg== 35 | 36 | ansi-styles@^3.2.1: 37 | version "3.2.1" 38 | resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" 39 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 40 | dependencies: 41 | color-convert "^1.9.0" 42 | 43 | argparse@^1.0.7: 44 | version "1.0.10" 45 | resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" 46 | integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== 47 | dependencies: 48 | sprintf-js "~1.0.2" 49 | 50 | balanced-match@^1.0.0: 51 | version "1.0.0" 52 | resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz" 53 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 54 | 55 | base64-js@^1.3.1: 56 | version "1.5.1" 57 | resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" 58 | integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== 59 | 60 | big.js@^5.2.2: 61 | version "5.2.2" 62 | resolved "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz" 63 | integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== 64 | 65 | brace-expansion@^1.1.7: 66 | version "1.1.11" 67 | resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" 68 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 69 | dependencies: 70 | balanced-match "^1.0.0" 71 | concat-map "0.0.1" 72 | 73 | buffer@^6.0.3: 74 | version "6.0.3" 75 | resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz" 76 | integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== 77 | dependencies: 78 | base64-js "^1.3.1" 79 | ieee754 "^1.2.1" 80 | 81 | builtin-modules@^1.1.1: 82 | version "1.1.1" 83 | resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz" 84 | integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= 85 | 86 | chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0: 87 | version "2.4.2" 88 | resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" 89 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 90 | dependencies: 91 | ansi-styles "^3.2.1" 92 | escape-string-regexp "^1.0.5" 93 | supports-color "^5.3.0" 94 | 95 | color-convert@^1.9.0: 96 | version "1.9.3" 97 | resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" 98 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 99 | dependencies: 100 | color-name "1.1.3" 101 | 102 | color-name@1.1.3: 103 | version "1.1.3" 104 | resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" 105 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 106 | 107 | commander@^2.12.1: 108 | version "2.20.3" 109 | resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" 110 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 111 | 112 | concat-map@0.0.1: 113 | version "0.0.1" 114 | resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" 115 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 116 | 117 | core-util-is@~1.0.0: 118 | version "1.0.2" 119 | resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" 120 | integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= 121 | 122 | debug@^2.2.0: 123 | version "2.6.9" 124 | resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" 125 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 126 | dependencies: 127 | ms "2.0.0" 128 | 129 | diff@^4.0.1: 130 | version "4.0.2" 131 | resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" 132 | integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== 133 | 134 | doctrine@^0.7.2: 135 | version "0.7.2" 136 | resolved "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz" 137 | integrity sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM= 138 | dependencies: 139 | esutils "^1.1.6" 140 | isarray "0.0.1" 141 | 142 | emojis-list@^3.0.0: 143 | version "3.0.0" 144 | resolved "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz" 145 | integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== 146 | 147 | enhanced-resolve@^3.0.0: 148 | version "3.4.1" 149 | resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz" 150 | integrity sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24= 151 | dependencies: 152 | graceful-fs "^4.1.2" 153 | memory-fs "^0.4.0" 154 | object-assign "^4.0.1" 155 | tapable "^0.2.7" 156 | 157 | errno@^0.1.3: 158 | version "0.1.8" 159 | resolved "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz" 160 | integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== 161 | dependencies: 162 | prr "~1.0.1" 163 | 164 | escape-string-regexp@^1.0.5: 165 | version "1.0.5" 166 | resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" 167 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 168 | 169 | esprima@^4.0.0: 170 | version "4.0.1" 171 | resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" 172 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 173 | 174 | esutils@^1.1.6: 175 | version "1.1.6" 176 | resolved "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz" 177 | integrity sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U= 178 | 179 | fs.realpath@^1.0.0: 180 | version "1.0.0" 181 | resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" 182 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 183 | 184 | function-bind@^1.1.1: 185 | version "1.1.1" 186 | resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" 187 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 188 | 189 | glob@^7.1.1: 190 | version "7.1.6" 191 | resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz" 192 | integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== 193 | dependencies: 194 | fs.realpath "^1.0.0" 195 | inflight "^1.0.4" 196 | inherits "2" 197 | minimatch "^3.0.4" 198 | once "^1.3.0" 199 | path-is-absolute "^1.0.0" 200 | 201 | graceful-fs@^4.1.2: 202 | version "4.2.4" 203 | resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz" 204 | integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== 205 | 206 | has-flag@^3.0.0: 207 | version "3.0.0" 208 | resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" 209 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 210 | 211 | has@^1.0.3: 212 | version "1.0.3" 213 | resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" 214 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 215 | dependencies: 216 | function-bind "^1.1.1" 217 | 218 | ieee754@^1.2.1: 219 | version "1.2.1" 220 | resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" 221 | integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== 222 | 223 | inflight@^1.0.4: 224 | version "1.0.6" 225 | resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" 226 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 227 | dependencies: 228 | once "^1.3.0" 229 | wrappy "1" 230 | 231 | inherits@2, inherits@~2.0.3: 232 | version "2.0.4" 233 | resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" 234 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 235 | 236 | iota-array@^1.0.0: 237 | version "1.0.0" 238 | resolved "https://registry.npmjs.org/iota-array/-/iota-array-1.0.0.tgz" 239 | integrity sha1-ge9X/l0FgUzVjCSDYyqZwwoOgIc= 240 | 241 | is-buffer@^1.0.2: 242 | version "1.1.6" 243 | resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" 244 | integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== 245 | 246 | is-core-module@^2.1.0: 247 | version "2.2.0" 248 | resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz" 249 | integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ== 250 | dependencies: 251 | has "^1.0.3" 252 | 253 | isarray@0.0.1: 254 | version "0.0.1" 255 | resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" 256 | integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= 257 | 258 | isarray@~1.0.0: 259 | version "1.0.0" 260 | resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" 261 | integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= 262 | 263 | js-tokens@^4.0.0: 264 | version "4.0.0" 265 | resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" 266 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 267 | 268 | js-yaml@^3.13.1: 269 | version "3.14.1" 270 | resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" 271 | integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== 272 | dependencies: 273 | argparse "^1.0.7" 274 | esprima "^4.0.0" 275 | 276 | json5@^1.0.1: 277 | version "1.0.1" 278 | resolved "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz" 279 | integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== 280 | dependencies: 281 | minimist "^1.2.0" 282 | 283 | loader-utils@^1.0.2: 284 | version "1.4.0" 285 | resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz" 286 | integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== 287 | dependencies: 288 | big.js "^5.2.2" 289 | emojis-list "^3.0.0" 290 | json5 "^1.0.1" 291 | 292 | memory-fs@^0.4.0: 293 | version "0.4.1" 294 | resolved "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz" 295 | integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= 296 | dependencies: 297 | errno "^0.1.3" 298 | readable-stream "^2.0.1" 299 | 300 | minimatch@^3.0.4: 301 | version "3.0.4" 302 | resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" 303 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 304 | dependencies: 305 | brace-expansion "^1.1.7" 306 | 307 | minimist@^1.2.0, minimist@^1.2.5: 308 | version "1.2.5" 309 | resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz" 310 | integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== 311 | 312 | mkdirp@^0.5.1: 313 | version "0.5.5" 314 | resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz" 315 | integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== 316 | dependencies: 317 | minimist "^1.2.5" 318 | 319 | ms@2.0.0: 320 | version "2.0.0" 321 | resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" 322 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 323 | 324 | mustache@^4.1.0: 325 | version "4.1.0" 326 | resolved "https://registry.npmjs.org/mustache/-/mustache-4.1.0.tgz" 327 | integrity sha512-0FsgP/WVq4mKyjolIyX+Z9Bd+3WS8GOwoUTyKXT5cTYMGeauNTi2HPCwERqseC1IHAy0Z7MDZnJBfjabd4O8GQ== 328 | 329 | mutable-buffer@2.0.3: 330 | version "2.0.3" 331 | resolved "https://registry.npmjs.org/mutable-buffer/-/mutable-buffer-2.0.3.tgz" 332 | integrity sha1-Z7ylVovxXT9gNftxbjiZ3ESQHIw= 333 | 334 | ndarray@^1.0.19: 335 | version "1.0.19" 336 | resolved "https://registry.npmjs.org/ndarray/-/ndarray-1.0.19.tgz" 337 | integrity sha512-B4JHA4vdyZU30ELBw3g7/p9bZupyew5a7tX1Y/gGeF2hafrPaQZhgrGQfsvgfYbgdFZjYwuEcnaobeM/WMW+HQ== 338 | dependencies: 339 | iota-array "^1.0.0" 340 | is-buffer "^1.0.2" 341 | 342 | object-assign@^4.0.1: 343 | version "4.1.1" 344 | resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" 345 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 346 | 347 | once@^1.3.0: 348 | version "1.4.0" 349 | resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" 350 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 351 | dependencies: 352 | wrappy "1" 353 | 354 | pako@^1.0.5: 355 | version "1.0.11" 356 | resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" 357 | integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== 358 | 359 | path-is-absolute@^1.0.0: 360 | version "1.0.1" 361 | resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" 362 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 363 | 364 | path-parse@^1.0.6: 365 | version "1.0.6" 366 | resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz" 367 | integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== 368 | 369 | process-nextick-args@~2.0.0: 370 | version "2.0.1" 371 | resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" 372 | integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== 373 | 374 | prr@~1.0.1: 375 | version "1.0.1" 376 | resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz" 377 | integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= 378 | 379 | readable-stream@^2.0.1: 380 | version "2.3.7" 381 | resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz" 382 | integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== 383 | dependencies: 384 | core-util-is "~1.0.0" 385 | inherits "~2.0.3" 386 | isarray "~1.0.0" 387 | process-nextick-args "~2.0.0" 388 | safe-buffer "~5.1.1" 389 | string_decoder "~1.1.1" 390 | util-deprecate "~1.0.1" 391 | 392 | resolve@^1.3.2: 393 | version "1.19.0" 394 | resolved "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz" 395 | integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== 396 | dependencies: 397 | is-core-module "^2.1.0" 398 | path-parse "^1.0.6" 399 | 400 | safe-buffer@~5.1.0, safe-buffer@~5.1.1: 401 | version "5.1.2" 402 | resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" 403 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 404 | 405 | semver@^5.0.1, semver@^5.3.0: 406 | version "5.7.1" 407 | resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" 408 | integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== 409 | 410 | sprintf-js@~1.0.2: 411 | version "1.0.3" 412 | resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" 413 | integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= 414 | 415 | string_decoder@~1.1.1: 416 | version "1.1.1" 417 | resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" 418 | integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== 419 | dependencies: 420 | safe-buffer "~5.1.0" 421 | 422 | supports-color@^5.3.0: 423 | version "5.5.0" 424 | resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" 425 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 426 | dependencies: 427 | has-flag "^3.0.0" 428 | 429 | tapable@^0.2.7: 430 | version "0.2.9" 431 | resolved "https://registry.npmjs.org/tapable/-/tapable-0.2.9.tgz" 432 | integrity sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A== 433 | 434 | ts-loader@^2.3.4: 435 | version "2.3.7" 436 | resolved "https://registry.npmjs.org/ts-loader/-/ts-loader-2.3.7.tgz" 437 | integrity sha512-8t3bu2FcEkXb+D4L+Cn8qiK2E2C6Ms4/GQChvz6IMbVurcFHLXrhW4EMtfaol1a1ASQACZGDUGit4NHnX9g7hQ== 438 | dependencies: 439 | chalk "^2.0.1" 440 | enhanced-resolve "^3.0.0" 441 | loader-utils "^1.0.2" 442 | semver "^5.0.1" 443 | 444 | tslib@^1.0.0, tslib@^1.8.0, tslib@^1.8.1: 445 | version "1.14.1" 446 | resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" 447 | integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== 448 | 449 | tslint-eslint-rules@^4.1.1: 450 | version "4.1.1" 451 | resolved "https://registry.npmjs.org/tslint-eslint-rules/-/tslint-eslint-rules-4.1.1.tgz" 452 | integrity sha1-fDDniC8mvCdr/5HSOEl1xp2viLo= 453 | dependencies: 454 | doctrine "^0.7.2" 455 | tslib "^1.0.0" 456 | tsutils "^1.4.0" 457 | 458 | tslint@^5.7.0: 459 | version "5.20.1" 460 | resolved "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz" 461 | integrity sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg== 462 | dependencies: 463 | "@babel/code-frame" "^7.0.0" 464 | builtin-modules "^1.1.1" 465 | chalk "^2.3.0" 466 | commander "^2.12.1" 467 | diff "^4.0.1" 468 | glob "^7.1.1" 469 | js-yaml "^3.13.1" 470 | minimatch "^3.0.4" 471 | mkdirp "^0.5.1" 472 | resolve "^1.3.2" 473 | semver "^5.3.0" 474 | tslib "^1.8.0" 475 | tsutils "^2.29.0" 476 | 477 | tsutils@^1.4.0: 478 | version "1.9.1" 479 | resolved "https://registry.npmjs.org/tsutils/-/tsutils-1.9.1.tgz" 480 | integrity sha1-ufmrROVa+WgYMdXyjQrur1x1DLA= 481 | 482 | tsutils@^2.29.0: 483 | version "2.29.0" 484 | resolved "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz" 485 | integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== 486 | dependencies: 487 | tslib "^1.8.1" 488 | 489 | typescript@^4.1.3: 490 | version "4.1.3" 491 | resolved "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz" 492 | integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== 493 | 494 | upng-js@2.1.0: 495 | version "2.1.0" 496 | resolved "https://registry.yarnpkg.com/upng-js/-/upng-js-2.1.0.tgz#7176e73973db361ca95d0fa14f958385db6b9dd2" 497 | integrity sha512-d3xzZzpMP64YkjP5pr8gNyvBt7dLk/uGI67EctzDuVp4lCZyVMo0aJO6l/VDlgbInJYDY6cnClLoBp29eKWI6g== 498 | dependencies: 499 | pako "^1.0.5" 500 | 501 | util-deprecate@~1.0.1: 502 | version "1.0.2" 503 | resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" 504 | integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= 505 | 506 | wrappy@1: 507 | version "1.0.2" 508 | resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" 509 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 510 | 511 | xml-parser@^1.2.1: 512 | version "1.2.1" 513 | resolved "https://registry.npmjs.org/xml-parser/-/xml-parser-1.2.1.tgz" 514 | integrity sha1-wx9MNPKXXbgq0BMiISBZJzYVb80= 515 | dependencies: 516 | debug "^2.2.0" 517 | --------------------------------------------------------------------------------