├── .gitignore ├── README.md ├── assets ├── all.icns ├── all.ico └── all.png ├── auto-update.js ├── command.js ├── escpos.js ├── example.js ├── index.html ├── node_modules ├── .bin │ ├── build.cmd │ ├── dircompare.cmd │ ├── run.cmd │ ├── semver.cmd │ ├── sshpk-conv.cmd │ ├── sshpk-sign.cmd │ ├── sshpk-verify.cmd │ └── uuid.cmd └── printer │ ├── .npmignore │ ├── .travis.yml │ ├── ChangeLog │ ├── Gruntfile.js │ ├── README.md │ ├── appveyor.yml │ ├── binding.gyp │ ├── build │ ├── Release │ │ ├── node_printer.exp │ │ ├── node_printer.lib │ │ ├── node_printer.node │ │ ├── node_printer.pdb │ │ └── obj │ │ │ └── node_printer │ │ │ ├── node_printer.obj │ │ │ ├── node_printer.tlog │ │ │ ├── CL.command.1.tlog │ │ │ ├── CL.read.1.tlog │ │ │ ├── link.command.1.tlog │ │ │ ├── link.read.1.tlog │ │ │ ├── link.write.1.tlog │ │ │ ├── node_printer.lastbuildstate │ │ │ └── node_printer.write.1u.tlog │ │ │ ├── node_printer_win.obj │ │ │ └── win_delay_load_hook.obj │ ├── binding.sln │ ├── config.gypi │ ├── node_printer.vcxproj │ └── node_printer.vcxproj.filters │ ├── examples │ ├── cancelJob.js │ ├── example_zebra_printer.js │ ├── getDefaultPrinterName.js │ ├── getPrinterDriverOptions.js │ ├── getPrinters.js │ ├── getSupportedFormats.js │ ├── getSupportedJobCommands.js │ ├── printFile.js │ ├── printPDFFileInBuffer.js │ ├── printPDFInWindows.js │ ├── print_raw.js │ └── test.pdf │ ├── lib │ ├── index.js │ └── printer.js │ ├── package.json │ ├── printer.js │ ├── src │ ├── macros.hh │ ├── node_printer.cc │ ├── node_printer.hpp │ ├── node_printer_posix.cc │ └── node_printer_win.cc │ └── tools │ └── getSourceFiles.py ├── package-lock.json ├── package.json └── printer.js /.gitignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /node_modules 3 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **注:仅支持`windows`系统** 2 | 3 | ## 1. 本地运行项目 4 | 5 | 使用 `npm install` 安装package.json中除了print之外的其他安装包 6 | 7 | 执行 `npm start`,首次运行会比较慢 8 | ``` 9 | npm install 10 | npm start 11 | ``` 12 | 13 | ## 2. 打包 14 | 15 | 使用 `nwjs-builder-phoenix` 打包,目前只生成windows版本 16 | ``` 17 | npm run dist 18 | ``` 19 | 20 | ## 3. 自动更新 21 | 22 | 需要在服务器上上传新的package.json和zip包 23 | 24 | 25 | ## 4. 目录结构 26 | ``` 27 | |-- assets ------------- logo文件 28 | |-- node_modules ------- 依赖包,除了普通的npm install之外,对printer做了特殊处理 29 | |-- auto-update.js ----- 自动更新相关代码 30 | |-- command.js --------- esc/pos常用指令集 31 | |-- escpos.js ---------- 常用打印函数的封装 32 | |-- example.js --------- 调用打印小票样例 33 | |-- index.html --------- 主文件 34 | |-- printer.js --------- 打印机函数的封装 35 | |-- package.json 36 | ``` 37 | 38 | ## 5. 整个项目遇到的难点、问题 39 | 40 | ### 1. `打包`相关 41 | 使用`nwjs-builder-phoenix` 42 | 43 | #### 问题:打开app巨慢 44 | - 原因:package.json中build:packed字段写成了true,打包时会将应用文件打包到exe中,导致每次运行exe文件都需要先解压再运行 45 | - 解决:改成false,将文件释放到exe并行目录中 46 | 47 | 48 | ### 2. `自动更新`相关 49 | 50 | > 1. 从现在运行的程序(旧版本)中检查版本清单 51 | > 2. 如果有高版本,将新包的zip文件下载到临时目录 52 | > 3. 解压zip包 53 | > 4. 在临时目录中运行新app并杀掉旧app进程 54 | > 5. 新app将会将自己复制到原始文件夹, 覆盖旧的应用程序 55 | > 6. 新应用程序将从原始文件夹中运行并退出进程 56 | 57 | #### 问题:使用中文名的productName,解压缩包时会中文乱码 58 | 59 | - 原因:`nwjs-autoupdater`可能对中文支持不友好 60 | - 解决:使用`node-webkit-updater`来自动更新 61 | 62 | #### 问题:使用`node-webkit-updater`官方例子自动更新时,在执行到替换旧版本时会报错 `EBUSY: resource busy or locked` 63 | 64 | - 原因:在运行安装程序时的步骤4中, 它的 cwd 默认为当前进程的 cwd, 可能是旧应用程序的目录。所以, 无法删除、覆盖安装目标目录, 因为正在使用它。 65 | - 解决:在源代码中添加 const newAppDir = path.dirname(newAppPath),再将 upd.runInstaller(newAppPath, [upd.getAppPath(), upd.getAppExec()],{}) 改为 upd.runInstaller(newAppPath, [upd.getAppPath(), upd.getAppExec()], {cwd: newAppDir} ) 66 | 67 | 68 | ### 3. `打印`相关 69 | 70 | #### 问题:printer环境配置 71 | 72 | - 原因:printer本质属于c++插件,需要特殊配置 73 | - 解决:安装python2.7版本,执行下面命令 74 | ```bash 75 | npm install printer --target_arch=x64 76 | cd node_modules/printer 77 | nw-gyp configure --target=${nw-version} 78 | nw-gyp rebuild --target=${nw-version} 79 | ``` 80 | 81 | 82 | #### 问题:不能打印汉字 83 | 84 | - 原因:node的buffer不支持gbk编码 85 | - 解决:使用iconv-lite进行bgk编码 86 | 87 | #### 问题:多列布局实现 88 | 89 | - 原因:不知道什么方式实现类似flex布局 90 | - 解决:使用sprint-js,一个神奇的补空格实现布局的方案 91 | 92 | #### 问题:分割线实现 93 | 94 | - 原因:没有分割线指令 95 | - 解决:结合sprint-js,用一行带下划线的空格来模拟 96 | 97 | #### 问题:切纸 98 | 99 | - 原因:一开始尝试的全切,当连续多张打印时,前面的纸会卡住后面的纸 100 | - 解决:改用留点半切 101 | 102 | 103 | 参考文献 104 | 105 | [微型热敏打印机指令集](https://wenku.baidu.com/view/6de8b8fec281e53a5902ff98#1?qq-pf-to=pcqq.c2c) -------------------------------------------------------------------------------- /assets/all.icns: -------------------------------------------------------------------------------- 1 | icns -------------------------------------------------------------------------------- /assets/all.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LittlehorseXie/nw-printer/ae517fa3a450ef8c591c09d28db3cf32f7396cdd/assets/all.ico -------------------------------------------------------------------------------- /assets/all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LittlehorseXie/nw-printer/ae517fa3a450ef8c591c09d28db3cf32f7396cdd/assets/all.png -------------------------------------------------------------------------------- /auto-update.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 自动更新 3 | */ 4 | 5 | const output = document.querySelector( "#output" ) 6 | const gui = require('nw.gui') //操作nw应用 7 | const updater = require('node-webkit-updater') //热更新 8 | const pkg = require('./package.json') 9 | const upd = new updater(pkg) 10 | const path = require('path') 11 | let copyPath = '', execPath = '' 12 | let progressTimer = null //设置一个定时器,用来模拟下载的进去条 13 | 14 | if (gui.App.argv.length) { 15 | copyPath = gui.App.argv[0] 16 | execPath = gui.App.argv[1] 17 | console.log('替换旧版本') 18 | output.innerHTML = copyPath + ' 替换旧版本 ' + execPath 19 | // 替换旧版本 20 | upd.install(copyPath, function(err) { 21 | if (!err) { 22 | // 重启 23 | output.innerHTML = '重启 ' + execPath 24 | upd.run(execPath, null) 25 | gui.App.quit() 26 | } else { 27 | output.innerHTML = err 28 | } 29 | }) 30 | } else { 31 | // 从manifest目录校验版本 32 | console.log('从manifest目录校验版本') 33 | output.innerHTML = '从manifest目录校验版本' 34 | upd.checkNewVersion(function(error, newVersionExists, manifest) { 35 | console.log(error, newVersionExists, manifest) 36 | if (!error && newVersionExists && confirm('检测到新版本,您需要升级吗?')) { 37 | // 有新版本显示下载进度条开始下载 38 | console.log('有新版本显示下载进度条开始下载') 39 | output.innerHTML = '有新版本显示下载进度条开始下载' 40 | setTimeout(function() { 41 | let startC = parseInt(Math.floor(Math.random() + 1) * 3) 42 | progressTimer = setInterval(function() { 43 | startC += Math.random() * 2 44 | if (startC >= 95) { 45 | clearInterval(progressTimer) 46 | startC = 95 47 | } 48 | console.log(startC.toFixed(2) + '%') 49 | output.innerHTML = startC.toFixed(2) + '%' 50 | }, 2000) 51 | }, 1000) 52 | 53 | // 下载新版本 54 | console.log('下载新版本') 55 | output.innerHTML = '下载新版本' 56 | upd.download(function(error, filename) { 57 | console.log(error, filename) 58 | if (!error) { 59 | clearInterval(progressTimer) 60 | // 下载完成关闭应用 61 | console.log('下载完成即将关闭应用') 62 | output.innerHTML = '下载完成即将关闭应用' 63 | upd.unpack(filename, function(error, newAppPath) { 64 | console.log(error, newAppPath) 65 | if (!error) { 66 | const newAppDir = path.dirname(newAppPath) 67 | console.log('重启应用') 68 | output.innerHTML = '重启应用' 69 | console.log(newAppPath, [upd.getAppPath(), upd.getAppExec()]) 70 | // 重启应用 71 | output.innerHTML = `${newAppPath}, [${upd.getAppPath()}, ${upd.getAppExec()}, cwd: ${newAppDir}]` 72 | upd.runInstaller(newAppPath, [upd.getAppPath(), upd.getAppExec()], {cwd: newAppDir}) 73 | gui.App.quit() 74 | } 75 | }, manifest) 76 | } 77 | }, manifest) 78 | } else if (!error && !newVersionExists) { 79 | console.log('您已经是最新版本') 80 | } 81 | }) 82 | } -------------------------------------------------------------------------------- /command.js: -------------------------------------------------------------------------------- 1 | const ESC = 0x1B, 2 | FS = 0x1C, 3 | GS = 0x1D 4 | 5 | const Command = { 6 | 7 | LF : [0x0A], // 打印并走纸 8 | ESC_init : [ESC, 0x40], // 初始化打印机 ESC @ 9 | 10 | ESC_exclamation : (n) => [ESC, 0x21, n], // ESC!n 11 | ESC_minus : (n) => [ESC, 0x2D, n], // 下划线0关闭,1开启1点宽,2开启2点宽 12 | ESC_rev : (n) => [ESC, 0x7B, n], // 设置0/取消1反向打印 ESC{n 13 | ESC_3 : (n) => [ESC, 0x33, n], // 设置字符行间距 14 | ESC_a : (n) => [ESC, 0x61, n], // 对齐模式0,48左/1,49中/2,50右 15 | ESC_d : (n) => [ESC, 0x64, n], // 打印并进纸n行 16 | ESC_e : (n) => [ESC, 0x65, n], // 打印并反向进纸n行 17 | ESC_E : (n) => [ESC, 0x45, n], // 设置1/取消0加粗模式 18 | ESC_G : (n) => [ESC, 0x47, n], // 设置1/取消0加重模式 19 | ESC_J : (n) => [ESC, 0x4A, n], // 打印并走纸n行 20 | 21 | FS_and : [FS, 0x26], // 进入汉字打印模式 22 | 23 | GS_exclamation : (n) => [GS, 0x21, n], // 字体放大 GS!n 24 | GS_B : (n) => [GS, 0x42, n], // 设置字符黑、白反转打印模式 25 | GS_h : (n) => [GS, 0x68, n], // 设置条码高度 26 | GS_v0 : (m) => [GS, 0x76, 0x30, m], // 打印点图数据 27 | GS_w : (n) => [GS, 0x77, n], // 设置条码宽度 28 | GS_W : (m, n) => [GS, 0x57, m, n], // 设置打印区宽度 29 | GS_V : (m) => [GS, 0x56, m], // 切纸 48全切 49六点半切 30 | 31 | 32 | 33 | } 34 | 35 | 36 | module.exports = Command -------------------------------------------------------------------------------- /escpos.js: -------------------------------------------------------------------------------- 1 | const Command = require('./command') 2 | const iconv = require('iconv-lite') 3 | const sprintf = require('sprintf-js').sprintf 4 | const MutableBuffer = require('mutable-buffer').MutableBuffer 5 | const middleCharLen = 22 6 | 7 | function getChnCount(str) { 8 | return str.replace(/[\u0391-\uFFE5]/g, 'aa').length - str.length 9 | } 10 | 11 | const Buffer = function() { 12 | this._buf = new MutableBuffer() 13 | this._buf.write(Command.ESC_init) 14 | } 15 | 16 | Buffer.prototype = { 17 | /** 18 | * 打印文字 19 | * @function setThreeCol 设置左中右布局 20 | * @param {string, string, string} 21 | * @function setTwoCol 设置左右布局 22 | * @param {string, string} 23 | * @function setDecLine 分割线 24 | * @param {} 25 | * @function setBoldOn 开启粗体模式 26 | * @param {} 27 | * @function setBoldOff 关闭粗体模式 28 | * @param {} 29 | * @function setLineHeight 设置字行高 30 | * @param {number} 31 | * @function setLine 换行并打印 32 | * @param {number} 33 | * @function setText 写文字 34 | * @param {string} 35 | * @function setTextDirection 设置文字布局 36 | * @param {string} 37 | * @function setTextSize 设置字体大小 38 | * @param {number} 39 | * @function cut 留点切纸 40 | * @param {} 41 | * @function getBuffer 获取字符 42 | * @param {} 43 | */ 44 | setThreeColText: function (l, m, r) { 45 | const chnLen = getChnCount(m) 46 | const buf = sprintf(`%3s %-${middleCharLen-chnLen}s %8s`, l, m, r) 47 | this._buf.write(iconv.encode(buf,'GBK')) 48 | this._buf.write(Command.LF) 49 | }, 50 | setThreeCol: function (first, second, third) { 51 | const chnLen = getChnCount(second) 52 | const charLen = second.length + chnLen 53 | // console.log(charLen, middleCharLen) 54 | if (charLen <= middleCharLen) { 55 | this.setThreeColText(first, second, third) 56 | } else { 57 | let charList = [2] 58 | for (let i = 1; i < second.length; i++) { 59 | const charCode = second.charCodeAt(i) 60 | if (charCode >= 0 && charCode <= 128) { 61 | charList.push(1 + charList[i - 1]) 62 | } else { 63 | charList.push(2 + charList[i - 1]) 64 | } 65 | } 66 | let indexList = [0] 67 | for (let i = 10; i < charList.length; i++) { 68 | if(charList[i] % 22 >= 0 && charList[i] % 22 < 2 && !(charList[i+1] && charList[i+1] % 22 >= 0 && charList[i+1] % 22 < 2)) { 69 | indexList.push(i) 70 | } 71 | } 72 | this.setThreeColText(first, second.slice(0, indexList[1]), third) 73 | // console.log(second.slice(0, indexList[1])) 74 | if (indexList.length === 2) { 75 | this.setThreeColText('', second.slice(indexList[1]), '') 76 | // console.log(second.slice(indexList[1])) 77 | } else { 78 | for(let i = 2; i < indexList.length; i++) { 79 | if (i === indexList.length - 1) { 80 | this.setThreeColText('', second.slice(indexList[i]), '') 81 | // console.log(second.slice(indexList[i])) 82 | } else { 83 | this.setThreeColText('', second.slice(indexList[i - 1], indexList[i]), '') 84 | // console.log(second.slice(indexList[i - 1], indexList[i])) 85 | } 86 | } 87 | } 88 | } 89 | return this 90 | }, 91 | setTwoCol: function (one, two) { 92 | const buf = sprintf(`%-${30-one.length}s%8s`, one, two) 93 | this._buf.write(iconv.encode(buf,'GBK')) 94 | this._buf.write(Command.LF) 95 | return this 96 | }, 97 | setDecLine: function () { 98 | this._buf.write(Command.ESC_minus(2)) 99 | this._buf.write(sprintf(`%40s`, ' ')) 100 | this._buf.write(Command.ESC_minus(0)) 101 | this._buf.write(sprintf(`%40s`, ' ')) 102 | this._buf.write(Command.LF) 103 | return this 104 | }, 105 | setBoldOn: function () { 106 | this._buf.write(Command.ESC_E(1)) 107 | return this 108 | }, 109 | setBoldOff: function () { 110 | this._buf.write(Command.ESC_E(0)) 111 | return this 112 | }, 113 | setLineHeight: function (num) { 114 | this._buf.write(Command.ESC_3(num)) 115 | return this 116 | }, 117 | setLine: function (n) { 118 | if (!n) { 119 | this._buf.write(Command.LF) 120 | return this 121 | } 122 | this._buf.write(Command.ESC_d(n)) 123 | return this 124 | }, 125 | setText: function (str, direction) { 126 | if (direction && direction === 'center') { 127 | this._buf.write(Command.ESC_a(49)) 128 | this._buf.write(iconv.encode(str,'GBK')) 129 | } else if(direction && direction === 'right') { 130 | this._buf.write(Command.ESC_a(50)) 131 | this._buf.write(iconv.encode(str,'GBK')) 132 | } else { 133 | this._buf.write(Command.ESC_a(48)) 134 | this._buf.write(iconv.encode(str,'GBK')) 135 | } 136 | this._buf.write(Command.LF) 137 | return this 138 | }, 139 | setTextDirection: function(direction) { 140 | if (direction && direction === 'center') { 141 | this._buf.write(Command.ESC_a(49)) 142 | } else if(direction && direction === 'right') { 143 | this._buf.write(Command.ESC_a(50)) 144 | } else { 145 | this._buf.write(Command.ESC_a(48)) 146 | } 147 | return this 148 | }, 149 | setTextSize: function (n) { 150 | switch(n) { 151 | case 2: 152 | this._buf.write(Command.GS_exclamation(17)) 153 | break 154 | default: 155 | this._buf.write(Command.GS_exclamation(0)) 156 | } 157 | return this 158 | }, 159 | cut: function() { 160 | this._buf.write(Command.GS_V(49)) 161 | return this 162 | }, 163 | getBuffer: function() { 164 | this._buf.flush() 165 | return this._buf.buffer 166 | } 167 | } 168 | 169 | module.exports = Buffer -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | const printer = require('./printer.js') 2 | 3 | const mockData = { 4 | id: 001, 5 | delivery_way: '外送', 6 | deliver_time: '立即送达', 7 | sku_detail: [{ 8 | quantity: 10, 9 | sku_name: '火米饼套餐', 10 | price: 20 11 | }], 12 | description: '多放火贝 火火火火', 13 | invoiced: '', 14 | package_fee: 1, 15 | deliver_fee: 10, 16 | total_price: 31, 17 | receiver_address: '火星1区101路1号', 18 | receiver_name: '火星人', 19 | receiver_phone: 00001, 20 | create_time: '0001-01-01', 21 | tagg_shop_name: '火星1号商店' 22 | } 23 | 24 | function getPrinterList() { 25 | const list = printer.getPrinterList() 26 | const res = [] 27 | list.forEach(item => res.push(item.name)) 28 | return res 29 | } 30 | 31 | function getPrinter(name) { 32 | return printer.getPrinter(name) 33 | } 34 | 35 | function printOrderRecive(name = '', data = {}) { 36 | console.log(name, data) 37 | const Buffer = require('./escpos.js') 38 | let buffer = new Buffer() 39 | 40 | buffer = buffer.setLineHeight(70) 41 | .setTextSize(2).setLineHeight(50).setText(data.id, 'center') 42 | .setTextSize(1).setLineHeight(100).setText(`${data.delivery_way} ${data.deliver_time}`, 'center') 43 | .setLineHeight(70).setDecLine() 44 | .setBoldOn() 45 | .setLineHeight(70) 46 | data.sku_detail && data.sku_detail.forEach(item => { 47 | buffer = buffer.setThreeCol(item.quantity, item.sku_name, `¥${item.price}`) 48 | }) 49 | buffer = buffer.setLine() 50 | .setLineHeight(100).setText(`备注:${data.description}`).setBoldOff() 51 | .setLineHeight(50).setDecLine() 52 | .setLineHeight(70) 53 | .setTwoCol('开具发票', data.invoiced) 54 | .setTwoCol('包装费', `¥${data.package_fee}`) 55 | .setTwoCol('配送费', `¥${data.deliver_fee}`) 56 | .setLineHeight(50) 57 | .setDecLine() 58 | .setBoldOn().setText(`合计:¥${data.total_price} `, 'right').setBoldOff() 59 | .setDecLine() 60 | .setLineHeight(70) 61 | .setText(`送货地址:${data.receiver_address}`) 62 | .setText(`客户:${data.receiver_name} ${data.receiver_phone}`) 63 | .setDecLine() 64 | .setText(`下单时间: ${data.create_time}`, 'center') 65 | .setLine(2) 66 | .setBoldOn().setText(`${data.tagg_shop_name} \n \n`, 'center').setBoldOff() 67 | .setLine(2) 68 | .cut() 69 | .getBuffer() 70 | 71 | printer.print(name, buffer) 72 | } 73 | 74 | module.exports = { 75 | mockData, 76 | getPrinterList, 77 | getPrinter, 78 | printOrderRecive 79 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 万象集 6 | 18 | 19 | 20 |

21 |     
22 |     
56 |     
57 |   
58 | 


--------------------------------------------------------------------------------
/node_modules/.bin/build.cmd:
--------------------------------------------------------------------------------
1 | @IF EXIST "%~dp0\node.exe" (
2 |   "%~dp0\node.exe"  "%~dp0\..\nwjs-builder-phoenix\dist\bin\build.js" %*
3 | ) ELSE (
4 |   @SETLOCAL
5 |   @SET PATHEXT=%PATHEXT:;.JS;=;%
6 |   node  "%~dp0\..\nwjs-builder-phoenix\dist\bin\build.js" %*
7 | )


--------------------------------------------------------------------------------
/node_modules/.bin/dircompare.cmd:
--------------------------------------------------------------------------------
1 | @IF EXIST "%~dp0\node.exe" (
2 |   "%~dp0\node.exe"  "%~dp0\..\dir-compare\dircompare.js" %*
3 | ) ELSE (
4 |   @SETLOCAL
5 |   @SET PATHEXT=%PATHEXT:;.JS;=;%
6 |   node  "%~dp0\..\dir-compare\dircompare.js" %*
7 | )


--------------------------------------------------------------------------------
/node_modules/.bin/run.cmd:
--------------------------------------------------------------------------------
1 | @IF EXIST "%~dp0\node.exe" (
2 |   "%~dp0\node.exe"  "%~dp0\..\nwjs-builder-phoenix\dist\bin\run.js" %*
3 | ) ELSE (
4 |   @SETLOCAL
5 |   @SET PATHEXT=%PATHEXT:;.JS;=;%
6 |   node  "%~dp0\..\nwjs-builder-phoenix\dist\bin\run.js" %*
7 | )


--------------------------------------------------------------------------------
/node_modules/.bin/semver.cmd:
--------------------------------------------------------------------------------
1 | @IF EXIST "%~dp0\node.exe" (
2 |   "%~dp0\node.exe"  "%~dp0\..\semver\bin\semver" %*
3 | ) ELSE (
4 |   @SETLOCAL
5 |   @SET PATHEXT=%PATHEXT:;.JS;=;%
6 |   node  "%~dp0\..\semver\bin\semver" %*
7 | )


--------------------------------------------------------------------------------
/node_modules/.bin/sshpk-conv.cmd:
--------------------------------------------------------------------------------
1 | @IF EXIST "%~dp0\node.exe" (
2 |   "%~dp0\node.exe"  "%~dp0\..\sshpk\bin\sshpk-conv" %*
3 | ) ELSE (
4 |   @SETLOCAL
5 |   @SET PATHEXT=%PATHEXT:;.JS;=;%
6 |   node  "%~dp0\..\sshpk\bin\sshpk-conv" %*
7 | )


--------------------------------------------------------------------------------
/node_modules/.bin/sshpk-sign.cmd:
--------------------------------------------------------------------------------
1 | @IF EXIST "%~dp0\node.exe" (
2 |   "%~dp0\node.exe"  "%~dp0\..\sshpk\bin\sshpk-sign" %*
3 | ) ELSE (
4 |   @SETLOCAL
5 |   @SET PATHEXT=%PATHEXT:;.JS;=;%
6 |   node  "%~dp0\..\sshpk\bin\sshpk-sign" %*
7 | )


--------------------------------------------------------------------------------
/node_modules/.bin/sshpk-verify.cmd:
--------------------------------------------------------------------------------
1 | @IF EXIST "%~dp0\node.exe" (
2 |   "%~dp0\node.exe"  "%~dp0\..\sshpk\bin\sshpk-verify" %*
3 | ) ELSE (
4 |   @SETLOCAL
5 |   @SET PATHEXT=%PATHEXT:;.JS;=;%
6 |   node  "%~dp0\..\sshpk\bin\sshpk-verify" %*
7 | )


--------------------------------------------------------------------------------
/node_modules/.bin/uuid.cmd:
--------------------------------------------------------------------------------
1 | @IF EXIST "%~dp0\node.exe" (
2 |   "%~dp0\node.exe"  "%~dp0\..\uuid\bin\uuid" %*
3 | ) ELSE (
4 |   @SETLOCAL
5 |   @SET PATHEXT=%PATHEXT:;.JS;=;%
6 |   node  "%~dp0\..\uuid\bin\uuid" %*
7 | )


--------------------------------------------------------------------------------
/node_modules/printer/.npmignore:
--------------------------------------------------------------------------------
1 | .gitignore
2 | *~
3 | .settings
4 | .c9*
5 | 


--------------------------------------------------------------------------------
/node_modules/printer/.travis.yml:
--------------------------------------------------------------------------------
 1 | env:
 2 |   matrix:
 3 |     - export NODE_VERSION="5.9"
 4 |     - export NODE_VERSION="4.4"
 5 |     - export NODE_VERSION="0.10"
 6 | matrix:
 7 |   fast_finish: true
 8 |   allow_failures:
 9 |     - env: NODE_VERSION="0.10"
10 |     - env: NODE_VERSION="iojs"
11 | before_install:
12 |   - git clone https://github.com/creationix/nvm.git ./.nvm
13 |   - source ./.nvm/nvm.sh
14 |   - nvm install $NODE_VERSION
15 |   - echo $NODE_VERSION
16 |   - nvm use $NODE_VERSION
17 |   - if [ $TRAVIS_OS_NAME == "linux" ]; then
18 |       sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test;
19 |       sudo apt-get -qq update;
20 |       sudo apt-get -qq install g++-4.8;
21 |       export CXX='g++-4.8';
22 |       sudo apt-get install -qq debhelper autotools-dev cups-ppdc libcups2-dev cups imagemagick ghostscript;
23 |     fi
24 |   - "export JOBS=4"
25 |   - BUILD_ONLY=true npm install
26 | before_script:
27 |   - git config --global user.name "Ion Lupascu"
28 |   - git config --global user.email ionlupascu@gmail.com
29 | git:
30 |   depth: 1
31 | branches:
32 |   only:
33 |     - master
34 | os:
35 |   - linux
36 |   - osx
37 | script: npm test
38 | 


--------------------------------------------------------------------------------
/node_modules/printer/ChangeLog:
--------------------------------------------------------------------------------
 1 | 2016.09.10, version 0.2.2
 2 | * correct memory leak (thanks to @kjlaw89)
 3 | 
 4 | 2015.10.22, version 0.2.1
 5 | * corrected printDirect with buffer data for node v4.X (#95)
 6 | * corrected segmentation fault from get default printer for node v0.10.X
 7 | 
 8 | 2015.09, version 0.2.0
 9 | * added possibility to compile with node v4.X
10 | * various bug/core dumps fix
11 | 
12 | 2015.04, version 0.1.2
13 | * posix: new method getPrinterDriverOptions(printerName) to retrieve PPD options
14 | * posix: new method getSelectedPaperSize(printerName) to retrieve the current paper size name
15 | * posix: new parameter `options` added to `printDirect` to set printer options (ex. `fit-to-page`, `media`, etc)
16 | * posix: new function printFile() to print a file
17 | 
18 | 2015.03.03, version 0.1.1
19 | * possibility to build for node-webkit with grunt
20 | 
21 | 2015.02.26, version 0.1.0
22 | * possibility to load native module for platform/arch: node_module_{platform}_{arch}.node
23 | 
24 | 2015.02.24, Version 0.0.5
25 | * added getDefaultPrinterName() method by returning the default printer name
26 | * make printer argument optional in getPrinter() and printDirect. If is missing, will try to print to default printer
27 | * resolve charest of getPrinter() #38
28 | * posix/win32: added more explicit errors
29 | * posix: do not throw error if job status code is not supported
30 | 
31 | 2015.01.30, Version 0.0.4
32 | * win: added RPC installed printers in getPrinters #40
33 | * posix: on some devices not all formats are supported, issue #23
34 | * posix: added link settings on build #28
35 | * corrected README.md
36 | * corrected examples
37 | 


--------------------------------------------------------------------------------
/node_modules/printer/Gruntfile.js:
--------------------------------------------------------------------------------
 1 | module.exports = function(grunt) {
 2 |     grunt.initConfig({
 3 |         gyp: {
 4 |             ia32: {
 5 |                 command: 'rebuild',
 6 |                 options: {
 7 |                     arch: 'ia32'
 8 |                 }
 9 |             },
10 |             x64: {
11 |                 command: 'rebuild',
12 |                 options: {
13 |                     arch: 'x64'
14 |                 }
15 |             }
16 |         },
17 |         "nw-gyp": {
18 |             ia32: {
19 |                 command: 'rebuild',
20 |                 options: {
21 |                     arch: 'ia32'
22 |                 }
23 |             },
24 |             x64: {
25 |                 command: 'rebuild',
26 |                 options: {
27 |                     arch: 'x64'
28 |                 }
29 |             }
30 |         },
31 |         copy: {
32 |             ia32: {
33 |                 files: [{src: 'build/Release/node_printer.node', dest: 'lib/node_printer_' + process.platform + '_ia32.node'}]
34 |             },
35 |             x64: {
36 |                 files: [{src: 'build/Release/node_printer.node', dest: 'lib/node_printer_' + process.platform + '_x64.node'}]
37 |             }
38 |         }
39 |     });
40 | 
41 |     grunt.loadNpmTasks('grunt-contrib-jshint');
42 |     grunt.loadNpmTasks('grunt-node-gyp');
43 |     grunt.loadNpmTasks('grunt-nw-gyp');
44 |     grunt.loadNpmTasks('grunt-contrib-copy');
45 | 
46 |     grunt.registerTask('build-nw-ia32', [
47 |             'nw-gyp:ia32',
48 |             'copy:ia32'
49 |     ]);
50 | 
51 |     grunt.registerTask('build-ia32', [
52 |             'gyp:ia32',
53 |             'copy:ia32'
54 |     ]);
55 | 
56 |     grunt.registerTask('build-x64', [
57 |             'gyp:x64',
58 |             'copy:x64'
59 |     ]);
60 | 
61 |     grunt.registerTask('build-nw-x64', [
62 |             'nw-gyp:x64',
63 |             'copy:x64'
64 |     ]);
65 | 
66 |     grunt.registerTask('build', [
67 |             'build-ia32',
68 |             'build-x64'
69 |     ]);
70 | 
71 |     grunt.registerTask('build-nw', [
72 |             'build-nw-ia32',
73 |             'build-nw-x64'
74 |     ]);
75 | }
76 | 


--------------------------------------------------------------------------------
/node_modules/printer/README.md:
--------------------------------------------------------------------------------
 1 | node-printer
 2 | ============
 3 | Native bind printers on POSIX and Windows OS from Node.js, iojs and node-webkit.
 4 | 
 5 |   
 6 |     
 7 |       
 8 |       
 9 |       
10 |     
11 |   
12 |   
13 |     
14 |       
17 |       
20 |       
23 |     
24 |   
25 | 
LinuxWindowsDependencies
15 | 16 | 18 | 19 | 21 | 22 |
26 | 27 | If you have a problem, ask question to [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/tojocky/node-printer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) or find/create a new [Github issue](https://github.com/tojocky/node-printer/issues) 28 | 29 | ### Reason: 30 | 31 | I was involved in a project where I need to print from Node.JS. This is the reason why I created this project and I want to share my code with others. 32 | 33 | 34 | ### Features: 35 | 36 | * no dependecies; 37 | * native method wrappers from Windows and POSIX (which uses [CUPS 1.4/MAC OS X 10.6](http://cups.org/)) APIs; 38 | * compatible with node v0.8.x, 0.9.x and v0.11.x (with 0.11.9 and 0.11.13); 39 | * compatible with node-webkit v0.8.x and 0.9.2; 40 | * `getPrinters()` to enumerate all installed printers with current jobs and statuses; 41 | * `getPrinter(printerName)` to get a specific/default printer info with current jobs and statuses; 42 | * `getPrinterDriverOptions(printerName)` ([POSIX](http://en.wikipedia.org/wiki/POSIX) only) to get a specific/default printer driver options such as supported paper size and other info 43 | * `getSelectedPaperSize(printerName)` ([POSIX](http://en.wikipedia.org/wiki/POSIX) only) to get a specific/default printer default paper size from its driver options 44 | * `getDefaultPrinterName()` return the default printer name; 45 | * `printDirect(options)` to send a job to a specific/default printer, now supports [CUPS options](http://www.cups.org/documentation.php/options.html) passed in the form of a JS object (see `cancelJob.js` example). To print a PDF from windows it is possible by using [node-pdfium module](https://github.com/tojocky/node-pdfium) to convert a PDF format into EMF and after to send to printer as EMF; 46 | * `printFile(options)` ([POSIX](http://en.wikipedia.org/wiki/POSIX) only) to print a file; 47 | * `getSupportedPrintFormats()` to get all possible print formats for printDirect method which depends on OS. `RAW` and `TEXT` are supported from all OS-es; 48 | * `getJob(printerName, jobId)` to get a specific job info including job status; 49 | * `setJob(printerName, jobId, command)` to send a command to a job (e.g. `'CANCEL'` to cancel the job); 50 | * `getSupportedJobCommands()` to get supported job commands for setJob() depends on OS. `'CANCEL'` command is supported from all OS-es. 51 | 52 | 53 | ### How to install: 54 | Make sure you have Python 2.x installed on your system. Windows users will also require Visual Studio (2013 Express is a good fit) 55 | 56 | from [npmjs.org](https://www.npmjs.org/package/printer) 57 | 58 | npm install -g node-gyp 59 | npm install printer --msvs_version=2013 60 | 61 | or [direct from git](https://www.npmjs.org/doc/cli/npm-install.html): 62 | 63 | npm install git+https://github.com/tojocky/node-printer.git 64 | if you want to to run in [nwjs](http://nwjs.io/) then rebuild the module with [nw-gyp](https://github.com/nwjs/nw-gyp): 65 | ``` 66 | npm install -g nw-gyp 67 | cd node_modules/printer 68 | nw-gyp rebuild 69 | ``` 70 | For specific distribution `--dist-url` node-gyp parameter should be used. Example for electron: 71 | ``` 72 | node-gyp rebuild --target=0.37.4 --arch=x64 --dist-url=https://atom.io/download/atom-shell 73 | ``` 74 | 75 | Ubuntu User : 76 | You need to install libcups2-dev package 77 | `sudo apt-get install libcups2-dev` 78 | 79 | 80 | ### How to use: 81 | 82 | See [examples](https://github.com/tojocky/node-printer/tree/master/examples) 83 | 84 | ### Author(s): 85 | 86 | * Ion Lupascu, ionlupascu@gmail.com 87 | 88 | ### Contibutors: 89 | 90 | Feel free to download, test and propose new futures 91 | 92 | ### License: 93 | [The MIT License (MIT)](http://opensource.org/licenses/MIT) 94 | -------------------------------------------------------------------------------- /node_modules/printer/appveyor.yml: -------------------------------------------------------------------------------- 1 | # appveyor file 2 | # http://www.appveyor.com/docs/appveyor-yml 3 | 4 | # Try out "interactive-mode" 5 | os: Windows Server 2012 R2 6 | 7 | # build version format 8 | version: "{build}" 9 | 10 | # Set a known clone folder 11 | clone_folder: c:\projects\node-printer 12 | 13 | # fix lineendings in Windows 14 | init: 15 | - git config --global core.autocrlf input 16 | - git config --global user.name "Ion Lupascu" 17 | - git config --global user.email ionlupascu@gmail.com 18 | 19 | # what combinations to test 20 | environment: 21 | matrix: 22 | # Node.js 23 | - nodejs_version: "0.10" 24 | - nodejs_version: "0.12" 25 | - nodejs_version: "4.4" 26 | - nodejs_version: "5.9" 27 | 28 | matrix: 29 | fast_finish: true 30 | allow_failures: 31 | - nodejs_version: "0.10" 32 | 33 | # Get the latest stable version of Node 0.STABLE.latest 34 | install: 35 | - ps: Install-Product node $env:nodejs_version 36 | - cmd: SET PATH=C:\Program Files (x86)\MSBuild\12.0\bin\;%PATH% 37 | - cmd: SET PATH=c:\python27;%PATH% 38 | - cmd: SET JOBS=4 39 | - cmd: SET BUILD_ONLY=true 40 | - cmd: npm install -g node-gyp 41 | - npm install --msvs_version=2013 42 | 43 | test_script: 44 | - node --version 45 | - npm --version 46 | # - cmd: npm test 47 | 48 | build: off 49 | 50 | branches: 51 | only: 52 | - master 53 | -------------------------------------------------------------------------------- /node_modules/printer/binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | 'targets': [ 3 | { 4 | 'target_name': 'node_printer', 5 | 'sources': [ 6 | # is like "ls -1 src/*.cc", but gyp does not support direct patterns on 7 | # sources 8 | ' 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {DEB1940F-78E4-FFEC-FD8A-00BE447D0E86} 23 | Win32Proj 24 | node_printer 25 | true 26 | x64 27 | 10.0.17763.0 28 | 29 | 30 | 31 | DynamicLibrary 32 | 33 | 34 | v141 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | $(ExecutablePath);$(MSBuildProjectDirectory)\..\bin\;$(MSBuildProjectDirectory)\..\bin\ 45 | true 46 | $(Configuration)\obj\$(ProjectName)\ 47 | true 48 | $(SolutionDir)$(Configuration)\ 49 | .node 50 | .node 51 | .node 52 | .node 53 | .node 54 | .node 55 | .node 56 | .node 57 | $(ProjectName) 58 | $(OutDir)\$(ProjectName).node 59 | 60 | 61 | 62 | C:\Users\SF\.nw-gyp\0.32.0\include\node;C:\Users\SF\.nw-gyp\0.32.0\src;C:\Users\SF\.nw-gyp\0.32.0\deps\uv\include;C:\Users\SF\.nw-gyp\0.32.0\deps\v8\include;%(AdditionalIncludeDirectories) 63 | /bigobj /d2FastFail /Zc:sizedDealloc- /Zc:threadSafeInit- /MP %(AdditionalOptions) 64 | EnableFastChecks 65 | true 66 | false 67 | ProgramDatabase 68 | 4251;4275;4267;4351;4355;4800;4595;4251;%(DisableSpecificWarnings) 69 | false 70 | false 71 | false 72 | Disabled 73 | NotUsing 74 | NODE_GYP_MODULE_NAME=node_printer;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;BUILDING_NODE_EXTENSION;DEBUG;_DEBUG;V8_ENABLE_CHECKS;%(PreprocessorDefinitions) 75 | MultiThreadedDebug 76 | true 77 | true 78 | false 79 | Level3 80 | 81 | 82 | kernel32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;user32.lib;uuid.lib;odbc32.lib;odbccp32.lib;delayimp.lib;credui.lib;dbghelp.lib;shlwapi.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;DelayImp.lib;"C:\Users\SF\.nw-gyp\0.32.0\x64\nw.lib";"C:\Users\SF\.nw-gyp\0.32.0\x64\node.lib" 83 | /ignore:4199 /maxilksize:0x7ff00000 /fastfail %(AdditionalOptions) 84 | true 85 | true 86 | iojs.exe;node.exe;%(DelayLoadDLLs) 87 | true 88 | false 89 | false 90 | $(OutDir)$(ProjectName).node 91 | true 92 | true 93 | .node 94 | MachineX64 95 | 96 | 97 | C:\Users\SF\.nw-gyp\0.32.0\include\node;C:\Users\SF\.nw-gyp\0.32.0\src;C:\Users\SF\.nw-gyp\0.32.0\deps\uv\include;C:\Users\SF\.nw-gyp\0.32.0\deps\v8\include;%(AdditionalIncludeDirectories) 98 | NODE_GYP_MODULE_NAME=node_printer;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;BUILDING_NODE_EXTENSION;DEBUG;_DEBUG;V8_ENABLE_CHECKS;%(PreprocessorDefinitions);%(PreprocessorDefinitions) 99 | 100 | 101 | 102 | 103 | C:\Users\SF\.nw-gyp\0.32.0\include\node;C:\Users\SF\.nw-gyp\0.32.0\src;C:\Users\SF\.nw-gyp\0.32.0\deps\uv\include;C:\Users\SF\.nw-gyp\0.32.0\deps\v8\include;%(AdditionalIncludeDirectories) 104 | /bigobj /d2FastFail /Zc:sizedDealloc- /Zc:threadSafeInit- /MP %(AdditionalOptions) 105 | EnableFastChecks 106 | true 107 | false 108 | ProgramDatabase 109 | 4251;4275;4267;4351;4355;4800;4595;4251;%(DisableSpecificWarnings) 110 | false 111 | false 112 | false 113 | Disabled 114 | NotUsing 115 | NODE_GYP_MODULE_NAME=node_printer;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;BUILDING_NODE_EXTENSION;DEBUG;_DEBUG;V8_ENABLE_CHECKS;%(PreprocessorDefinitions) 116 | MultiThreadedDebug 117 | true 118 | true 119 | false 120 | Level3 121 | 122 | 123 | kernel32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;user32.lib;uuid.lib;odbc32.lib;odbccp32.lib;delayimp.lib;credui.lib;dbghelp.lib;shlwapi.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;DelayImp.lib;"C:\Users\SF\.nw-gyp\0.32.0\x64\nw.lib";"C:\Users\SF\.nw-gyp\0.32.0\x64\node.lib" 124 | /ignore:4199 /maxilksize:0x7ff00000 /fastfail %(AdditionalOptions) 125 | true 126 | true 127 | iojs.exe;node.exe;%(DelayLoadDLLs) 128 | true 129 | false 130 | false 131 | $(OutDir)$(ProjectName).node 132 | true 133 | true 134 | .node 135 | MachineX64 136 | 137 | 138 | C:\Users\SF\.nw-gyp\0.32.0\include\node;C:\Users\SF\.nw-gyp\0.32.0\src;C:\Users\SF\.nw-gyp\0.32.0\deps\uv\include;C:\Users\SF\.nw-gyp\0.32.0\deps\v8\include;%(AdditionalIncludeDirectories) 139 | NODE_GYP_MODULE_NAME=node_printer;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;BUILDING_NODE_EXTENSION;DEBUG;_DEBUG;V8_ENABLE_CHECKS;%(PreprocessorDefinitions);%(PreprocessorDefinitions) 140 | 141 | 142 | 143 | 144 | C:\Users\SF\.nw-gyp\0.32.0\include\node;C:\Users\SF\.nw-gyp\0.32.0\src;C:\Users\SF\.nw-gyp\0.32.0\deps\uv\include;C:\Users\SF\.nw-gyp\0.32.0\deps\v8\include;%(AdditionalIncludeDirectories) 145 | /bigobj /d2FastFail /Zc:sizedDealloc- /Zc:threadSafeInit- /MP %(AdditionalOptions) 146 | true 147 | false 148 | ProgramDatabase 149 | 4251;4275;4267;4351;4355;4800;4595;4251;%(DisableSpecificWarnings) 150 | false 151 | Speed 152 | true 153 | AnySuitable 154 | true 155 | true 156 | Full 157 | NotUsing 158 | NODE_GYP_MODULE_NAME=node_printer;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;BUILDING_NODE_EXTENSION;%(PreprocessorDefinitions) 159 | MultiThreaded 160 | false 161 | true 162 | true 163 | false 164 | Level3 165 | false 166 | 167 | 168 | kernel32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;user32.lib;uuid.lib;odbc32.lib;odbccp32.lib;delayimp.lib;credui.lib;dbghelp.lib;shlwapi.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;DelayImp.lib;"C:\Users\SF\.nw-gyp\0.32.0\x64\nw.lib";"C:\Users\SF\.nw-gyp\0.32.0\x64\node.lib" 169 | /ignore:4199 /maxilksize:0x7ff00000 /fastfail %(AdditionalOptions) 170 | true 171 | true 172 | iojs.exe;node.exe;%(DelayLoadDLLs) 173 | true 174 | false 175 | false 176 | $(OutDir)$(ProjectName).node 177 | true 178 | true 179 | .node 180 | MachineX64 181 | 182 | 183 | C:\Users\SF\.nw-gyp\0.32.0\include\node;C:\Users\SF\.nw-gyp\0.32.0\src;C:\Users\SF\.nw-gyp\0.32.0\deps\uv\include;C:\Users\SF\.nw-gyp\0.32.0\deps\v8\include;%(AdditionalIncludeDirectories) 184 | NODE_GYP_MODULE_NAME=node_printer;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;BUILDING_NODE_EXTENSION;%(PreprocessorDefinitions);%(PreprocessorDefinitions) 185 | 186 | 187 | 188 | 189 | C:\Users\SF\.nw-gyp\0.32.0\include\node;C:\Users\SF\.nw-gyp\0.32.0\src;C:\Users\SF\.nw-gyp\0.32.0\deps\uv\include;C:\Users\SF\.nw-gyp\0.32.0\deps\v8\include;%(AdditionalIncludeDirectories) 190 | /bigobj /d2FastFail /Zc:sizedDealloc- /Zc:threadSafeInit- /MP %(AdditionalOptions) 191 | true 192 | false 193 | ProgramDatabase 194 | 4251;4275;4267;4351;4355;4800;4595;4251;%(DisableSpecificWarnings) 195 | false 196 | Speed 197 | true 198 | AnySuitable 199 | true 200 | true 201 | Full 202 | NotUsing 203 | NODE_GYP_MODULE_NAME=node_printer;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;BUILDING_NODE_EXTENSION;%(PreprocessorDefinitions) 204 | MultiThreaded 205 | false 206 | true 207 | true 208 | false 209 | Level3 210 | false 211 | 212 | 213 | kernel32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;user32.lib;uuid.lib;odbc32.lib;odbccp32.lib;delayimp.lib;credui.lib;dbghelp.lib;shlwapi.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;DelayImp.lib;"C:\Users\SF\.nw-gyp\0.32.0\x64\nw.lib";"C:\Users\SF\.nw-gyp\0.32.0\x64\node.lib" 214 | /ignore:4199 /maxilksize:0x7ff00000 /fastfail %(AdditionalOptions) 215 | true 216 | true 217 | iojs.exe;node.exe;%(DelayLoadDLLs) 218 | true 219 | false 220 | false 221 | $(OutDir)$(ProjectName).node 222 | true 223 | true 224 | .node 225 | MachineX64 226 | 227 | 228 | C:\Users\SF\.nw-gyp\0.32.0\include\node;C:\Users\SF\.nw-gyp\0.32.0\src;C:\Users\SF\.nw-gyp\0.32.0\deps\uv\include;C:\Users\SF\.nw-gyp\0.32.0\deps\v8\include;%(AdditionalIncludeDirectories) 229 | NODE_GYP_MODULE_NAME=node_printer;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;BUILDING_NODE_EXTENSION;%(PreprocessorDefinitions);%(PreprocessorDefinitions) 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | true 241 | 242 | 243 | 244 | 245 | 246 | 247 | -------------------------------------------------------------------------------- /node_modules/printer/build/node_printer.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {739DB09A-CC57-A953-A6CF-F64FA08E4FA7} 6 | 7 | 8 | {8CDEE807-BC53-E450-C8B8-4DEBB66742D4} 9 | 10 | 11 | {739DB09A-CC57-A953-A6CF-F64FA08E4FA7} 12 | 13 | 14 | {8CDEE807-BC53-E450-C8B8-4DEBB66742D4} 15 | 16 | 17 | {7B735499-E5DD-1C2B-6C26-70023832A1CF} 18 | 19 | 20 | {E9F714C1-DA89-54E2-60CF-39FEB20BF756} 21 | 22 | 23 | {A3A55A83-A854-1856-B404-AF9F7473EA90} 24 | 25 | 26 | {F852EB63-437C-846A-220F-8D9ED6DAEC1D} 27 | 28 | 29 | {D51E5808-912B-5C70-4BB7-475D1DBFA067} 30 | 31 | 32 | {741E0E76-39B2-B1AB-9FA1-F1A20B16F295} 33 | 34 | 35 | {56DF7A98-063D-FB9D-485C-089023B4C16A} 36 | 37 | 38 | {3F3DA212-C923-AD55-6808-5CDB089DD269} 39 | 40 | 41 | {8CDEE807-BC53-E450-C8B8-4DEBB66742D4} 42 | 43 | 44 | {739DB09A-CC57-A953-A6CF-F64FA08E4FA7} 45 | 46 | 47 | {739DB09A-CC57-A953-A6CF-F64FA08E4FA7} 48 | 49 | 50 | {8CDEE807-BC53-E450-C8B8-4DEBB66742D4} 51 | 52 | 53 | {158E591E-B6EA-0C85-8F5A-18EAFA09B4CE} 54 | 55 | 56 | 57 | 58 | ..\src 59 | 60 | 61 | ..\src 62 | 63 | 64 | C:\Users\SF\AppData\Roaming\npm\node_modules\nw-gyp\src 65 | 66 | 67 | .. 68 | 69 | 70 | ..\src\_excluded_files 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /node_modules/printer/examples/cancelJob.js: -------------------------------------------------------------------------------- 1 | var printer = require("../lib"), 2 | util = require('util'), 3 | printerName = 'Foxit Reader PDF Printer', 4 | printerFormat = 'TEXT'; 5 | 6 | printer.printDirect({ 7 | data:"print from Node.JS buffer", // or simple String: "some text" 8 | printer:printerName, // printer name 9 | type: printerFormat, // type: RAW, TEXT, PDF, JPEG, .. depends on platform 10 | options: // supported page sizes may be retrieved using getPrinterDriverOptions, supports CUPS printing options 11 | { 12 | media: 'Letter', 13 | 'fit-to-page': true 14 | }, 15 | success:function(jobID){ 16 | console.log("sent to printer with ID: "+jobID); 17 | var jobInfo = printer.getJob(printerName, jobID); 18 | console.log("current job info:"+util.inspect(jobInfo, {depth: 10, colors:true})); 19 | if(jobInfo.status.indexOf('PRINTED') !== -1) 20 | { 21 | console.log('too late, already printed'); 22 | return; 23 | } 24 | console.log('cancelling...'); 25 | var is_ok = printer.setJob(printerName, jobID, 'CANCEL'); 26 | console.log("cancelled: "+is_ok); 27 | try{ 28 | console.log("current job info:"+util.inspect(printer.getJob(printerName, jobID), {depth: 10, colors:true})); 29 | }catch(err){ 30 | console.log('job deleted. err:'+err); 31 | } 32 | }, 33 | error:function(err){console.log(err);} 34 | }); 35 | -------------------------------------------------------------------------------- /node_modules/printer/examples/example_zebra_printer.js: -------------------------------------------------------------------------------- 1 | var printer = require("../lib") 2 | , template = "N\nS4\nD15\nq400\nR\nB20,10,0,1,2,30,173,B,\"barcode\"\nP0\n"; 3 | 4 | function printZebra(barcode_text, printer_name){ 5 | printer.printDirect({data:template.replace(/barcode/, barcode_text) 6 | , printer:printer_name 7 | , type: "RAW" 8 | , success:function(){ 9 | console.log("printed: "+barcode_text); 10 | } 11 | , error:function(err){console.log(err);} 12 | }); 13 | } 14 | 15 | printZebra("123", "ZEBRA"); 16 | -------------------------------------------------------------------------------- /node_modules/printer/examples/getDefaultPrinterName.js: -------------------------------------------------------------------------------- 1 | var printer = require("../lib"); 2 | 3 | console.log('default printer name: ' + (printer.getDefaultPrinterName() || 'is not defined on your computer')); 4 | 5 | -------------------------------------------------------------------------------- /node_modules/printer/examples/getPrinterDriverOptions.js: -------------------------------------------------------------------------------- 1 | var printer = require("../lib"), 2 | util = require('util'), 3 | printers = printer.getPrinters(); 4 | 5 | printers.forEach(function(iPrinter, i){ 6 | console.log('' + i + 'ppd for printer "' + iPrinter.name + '":' + util.inspect(printer.getPrinterDriverOptions(iPrinter.name), {colors:true, depth:10} )); 7 | console.log('\tselected page size:'+ printer.getSelectedPaperSize(iPrinter.name) + '\n'); 8 | }); 9 | 10 | -------------------------------------------------------------------------------- /node_modules/printer/examples/getPrinters.js: -------------------------------------------------------------------------------- 1 | var printer = require("../lib"), 2 | util = require('util'); 3 | console.log("installed printers:\n"+util.inspect(printer.getPrinters(), {colors:true, depth:10})); 4 | -------------------------------------------------------------------------------- /node_modules/printer/examples/getSupportedFormats.js: -------------------------------------------------------------------------------- 1 | var printer = require("../lib"), 2 | util = require('util'); 3 | console.log("supported formats are:\n"+util.inspect(printer.getSupportedPrintFormats(), {colors:true, depth:10})); 4 | -------------------------------------------------------------------------------- /node_modules/printer/examples/getSupportedJobCommands.js: -------------------------------------------------------------------------------- 1 | var printer = require("../lib"), //=require('pritner') 2 | util = require('util'); 3 | console.log("supported job commands:\n"+util.inspect(printer.getSupportedJobCommands(), {colors:true, depth:10})); 4 | -------------------------------------------------------------------------------- /node_modules/printer/examples/printFile.js: -------------------------------------------------------------------------------- 1 | // use: node printFile.js [filePath printerName] 2 | var printer = require("../lib"), 3 | filename = process.argv[2] || __filename; 4 | 5 | console.log('platform:', process.platform); 6 | console.log('try to print file: ' + filename); 7 | 8 | if( process.platform != 'win32') { 9 | printer.printFile({filename:filename, 10 | printer: process.env[3], // printer name, if missing then will print to default printer 11 | success:function(jobID){ 12 | console.log("sent to printer with ID: "+jobID); 13 | }, 14 | error:function(err){ 15 | console.log(err); 16 | } 17 | }); 18 | } else { 19 | // not yet implemented, use printDirect and text 20 | var fs = require('fs'); 21 | printer.printDirect({data:fs.readFileSync(filename), 22 | printer: process.env[3], // printer name, if missing then will print to default printer 23 | success:function(jobID){ 24 | console.log("sent to printer with ID: "+jobID); 25 | }, 26 | error:function(err){ 27 | console.log(err); 28 | } 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /node_modules/printer/examples/printPDFFileInBuffer.js: -------------------------------------------------------------------------------- 1 | // Windows does not support PDF formats, but you can use imagemagick-native to achieve conversion from PDF to EMF. 2 | 3 | var printer = require("../lib"), 4 | fs = require('fs'), 5 | path = require('path'), 6 | filename = process.argv[2], 7 | printername = process.argv[3]; 8 | 9 | if(process.platform == 'win32') { 10 | throw 'Not yet supported for win32' 11 | } 12 | 13 | if(!filename || filename == '-h') { 14 | throw 'PDF file name is missing. Please use the following params: [printername]' 15 | } 16 | 17 | filename = path.resolve(process.cwd(), filename); 18 | console.log('printing file name ' + filename); 19 | 20 | fs.readFile(filename, function(err, data){ 21 | if(err) { 22 | console.error('err:' + err); 23 | return; 24 | } 25 | console.log('data type is: '+typeof(data) + ', is buffer: ' + Buffer.isBuffer(data)); 26 | printer.printDirect({ 27 | data: data, 28 | type: 'PDF', 29 | success: function(id) { 30 | console.log('printed with id ' + id); 31 | }, 32 | error: function(err) { 33 | console.error('error on printing: ' + err); 34 | } 35 | }) 36 | }); 37 | 38 | -------------------------------------------------------------------------------- /node_modules/printer/examples/printPDFInWindows.js: -------------------------------------------------------------------------------- 1 | // Windows does not support PDF formats, but you can use imagemagick-native to achieve conversion from PDF to EMF. 2 | 3 | var printer = require("../lib"), 4 | imagemagick, // will be loaded later with proper error. 5 | fs = require('fs'), 6 | filename = process.argv[2], 7 | printername = process.argv[2]; 8 | 9 | if(process.platform !== 'win32') { 10 | throw 'This application can be run only on win32 as a demo of print PDF image' 11 | } 12 | 13 | if(!filename) { 14 | throw 'PDF file name is missing. Please use the following params: [printername]' 15 | } 16 | 17 | try { 18 | imagemagick = require('imagemagick-native'); 19 | } catch(e) { 20 | throw 'please install imagemagick-native: `npm install imagemagick-native`' 21 | } 22 | 23 | var data = fs.readFileSync(filename); 24 | 25 | console.log('data: ' + data.toString().substr(0, 20)); 26 | 27 | //console.log(imagemagick.identify({srcData: data})); 28 | 29 | // First convert PDF into 30 | imagemagick.convert({ 31 | srcData: data, 32 | srcFormat: 'PDF', 33 | format: 'EMF', 34 | }, function(err, buffer) { 35 | if (err) { 36 | throw 'something went wrong on converting to EMF: ' + err; 37 | } 38 | 39 | // Now we have EMF file, send it to printer as EMF format 40 | printer.printDirect({ 41 | data: buffer, 42 | type: 'EMF', 43 | success: function(id) { 44 | console.log('printed with id ' + id); 45 | }, 46 | error: function(err) { 47 | console.error('error on printing: ' + err); 48 | } 49 | }) 50 | }) 51 | 52 | 53 | -------------------------------------------------------------------------------- /node_modules/printer/examples/print_raw.js: -------------------------------------------------------------------------------- 1 | var printer = require("../lib"); 2 | 3 | printer.printDirect({data:"print from Node.JS buffer" // or simple String: "some text" 4 | //, printer:'Foxit Reader PDF Printer' // printer name, if missing then will print to default printer 5 | , type: 'RAW' // type: RAW, TEXT, PDF, JPEG, .. depends on platform 6 | , success:function(jobID){ 7 | console.log("sent to printer with ID: "+jobID); 8 | } 9 | , error:function(err){console.log(err);} 10 | }); 11 | -------------------------------------------------------------------------------- /node_modules/printer/examples/test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LittlehorseXie/nw-printer/ae517fa3a450ef8c591c09d28db3cf32f7396cdd/node_modules/printer/examples/test.pdf -------------------------------------------------------------------------------- /node_modules/printer/lib/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./printer'); -------------------------------------------------------------------------------- /node_modules/printer/lib/printer.js: -------------------------------------------------------------------------------- 1 | var printer_helper = {}, 2 | fs = require("fs"), 3 | child_process = require("child_process"), 4 | os = require("os"), 5 | path = require("path"), 6 | native_lib_path = path.join(__dirname, '../build/Release/node_printer.node'), 7 | printer_helper; 8 | 9 | if(fs.existsSync(native_lib_path)) { 10 | printer_helper = require(native_lib_path); 11 | } else { 12 | printer_helper = require('./node_printer_'+process.platform+'_'+process.arch+'.node'); 13 | } 14 | 15 | /** Return all installed printers including active jobs 16 | */ 17 | module.exports.getPrinters = getPrinters; 18 | 19 | /** send data to printer 20 | */ 21 | module.exports.printDirect = printDirect; 22 | 23 | /// send file to printer 24 | module.exports.printFile = printFile; 25 | 26 | /** Get supported print format for printDirect 27 | */ 28 | module.exports.getSupportedPrintFormats = printer_helper.getSupportedPrintFormats; 29 | 30 | /** 31 | * Get possible job command for setJob. It depends on os. 32 | * @return Array of string. e.g.: DELETE, PAUSE, RESUME 33 | */ 34 | module.exports.getSupportedJobCommands = printer_helper.getSupportedJobCommands; 35 | 36 | /** get printer info object. It includes all active jobs 37 | */ 38 | module.exports.getPrinter = getPrinter; 39 | module.exports.getSelectedPaperSize = getSelectedPaperSize; 40 | module.exports.getPrinterDriverOptions = getPrinterDriverOptions; 41 | 42 | /// Return default printer name 43 | module.exports.getDefaultPrinterName = getDefaultPrinterName; 44 | 45 | /** get printer job info object 46 | */ 47 | module.exports.getJob = getJob; 48 | module.exports.setJob = setJob; 49 | 50 | /** 51 | * return user defined printer, according to https://www.cups.org/documentation.php/doc-2.0/api-cups.html#cupsGetDefault2 : 52 | * "Applications should use the cupsGetDests and cupsGetDest functions to get the user-defined default printer, 53 | * as this function does not support the lpoptions-defined default printer" 54 | */ 55 | function getDefaultPrinterName() { 56 | var printerName = printer_helper.getDefaultPrinterName(); 57 | if(printerName) { 58 | return printerName; 59 | } 60 | 61 | // seems correct posix behaviour 62 | var printers= getPrinters(); 63 | for(i in printers) { 64 | var printer = printers[i]; 65 | if(printer.isDefault === true) { 66 | return printer.name; 67 | } 68 | } 69 | 70 | // printer not found, return nothing(undefined) 71 | } 72 | 73 | /** Get printer info with jobs 74 | * @param printerName printer name to extract the info 75 | * @return printer object info: 76 | * TODO: to enum all possible attributes 77 | */ 78 | function getPrinter(printerName) 79 | { 80 | if(!printerName) { 81 | printerName = getDefaultPrinterName(); 82 | } 83 | var printer = printer_helper.getPrinter(printerName); 84 | correctPrinterinfo(printer); 85 | return printer; 86 | } 87 | 88 | /** Get printer driver options includes advanced options like supported paper size 89 | * @param printerName printer name to extract the info (default printer used if printer is not provided) 90 | * @return printer driver info: 91 | */ 92 | function getPrinterDriverOptions(printerName) 93 | { 94 | if(!printerName) { 95 | printerName = getDefaultPrinterName(); 96 | } 97 | 98 | return printer_helper.getPrinterDriverOptions(printerName); 99 | } 100 | 101 | /** Finds selected paper size pertaining to the specific printer out of all supported ones in driver_options 102 | * @param printerName printer name to extract the info (default printer used if printer is not provided) 103 | * @return selected paper size 104 | */ 105 | function getSelectedPaperSize(printerName){ 106 | var driver_options = getPrinterDriverOptions(printerName); 107 | var selectedSize = ""; 108 | if (driver_options && driver_options.PageSize) { 109 | Object.keys(driver_options.PageSize).forEach(function(key){ 110 | if (driver_options.PageSize[key]) 111 | selectedSize = key; 112 | }); 113 | } 114 | return selectedSize; 115 | } 116 | 117 | function getJob(printerName, jobId) 118 | { 119 | return printer_helper.getJob(printerName, jobId); 120 | } 121 | 122 | function setJob(printerName, jobId, command) 123 | { 124 | return printer_helper.setJob(printerName, jobId, command); 125 | } 126 | 127 | function getPrinters(){ 128 | var printers = printer_helper.getPrinters(); 129 | for(i in printers){ 130 | correctPrinterinfo(printers[i]); 131 | } 132 | return printers; 133 | } 134 | 135 | function correctPrinterinfo(printer) { 136 | if(printer.status || !printer.options || !printer.options['printer-state']){ 137 | return; 138 | } 139 | 140 | var status = printer.options['printer-state']; 141 | // Add posix status 142 | if(status == '3'){ 143 | status = 'IDLE' 144 | } 145 | else if(status == '4'){ 146 | status = 'PRINTING' 147 | } 148 | else if(status == '5'){ 149 | status = 'STOPPED' 150 | } 151 | 152 | // correct date type 153 | var k; 154 | for(k in printer.options) { 155 | if(/time$/.test(k) && printer.options[k] && !(printer.options[k] instanceof Date)) { 156 | printer.options[k] = new Date(printer.options[k] * 1000); 157 | } 158 | } 159 | 160 | printer.status = status; 161 | } 162 | 163 | /* 164 | print raw data. This function is intend to be asynchronous 165 | 166 | parameters: 167 | parameters - Object, parameters objects with the following structure: 168 | data - String, mandatory, data to printer 169 | printer - String, optional, name of the printer, if missing, will try to print to default printer 170 | docname - String, optional, name of document showed in printer status 171 | type - String, optional, only for wind32, data type, one of the RAW, TEXT 172 | options - JS object with CUPS options, optional 173 | success - Function, optional, callback function 174 | error - Function, optional, callback function if exists any error 175 | 176 | or 177 | 178 | data - String, mandatory, data to printer 179 | printer - String, optional, name of the printer, if missing, will try to print to default printer 180 | docname - String, optional, name of document showed in printer status 181 | type - String, optional, data type, one of the RAW, TEXT 182 | options - JS object with CUPS options, optional 183 | success - Function, optional, callback function with first argument job_id 184 | error - Function, optional, callback function if exists any error 185 | */ 186 | function printDirect(parameters){ 187 | var data = parameters 188 | , printer 189 | , docname 190 | , type 191 | , options 192 | , success 193 | , error; 194 | 195 | if(arguments.length==1){ 196 | //TODO: check parameters type 197 | //if (typeof parameters ) 198 | data = parameters.data; 199 | printer = parameters.printer; 200 | docname = parameters.docname; 201 | type = parameters.type; 202 | options = parameters.options||{}; 203 | success = parameters.success; 204 | error = parameters.error; 205 | }else{ 206 | printer = arguments[1]; 207 | type = arguments[2]; 208 | docname = arguments[3]; 209 | options = arguments[4]; 210 | success = arguments[5]; 211 | error = arguments[6]; 212 | } 213 | 214 | if(!type){ 215 | type = "RAW"; 216 | } 217 | 218 | // Set default printer name 219 | if(!printer) { 220 | printer = getDefaultPrinterName(); 221 | } 222 | 223 | type = type.toUpperCase(); 224 | 225 | if(!docname){ 226 | docname = "node print job"; 227 | } 228 | 229 | if (!options){ 230 | options = {}; 231 | } 232 | 233 | //TODO: check parameters type 234 | if(printer_helper.printDirect){// call C++ binding 235 | try{ 236 | var res = printer_helper.printDirect(data, printer, docname, type, options); 237 | if(res){ 238 | success(res); 239 | }else{ 240 | error(Error("Something wrong in printDirect")); 241 | } 242 | }catch (e){ 243 | error(e); 244 | } 245 | }else{ 246 | error("Not supported"); 247 | } 248 | } 249 | 250 | /** 251 | parameters: 252 | parameters - Object, parameters objects with the following structure: 253 | filename - String, mandatory, data to printer 254 | docname - String, optional, name of document showed in printer status 255 | printer - String, optional, mane of the printer, if missed, will try to retrieve the default printer name 256 | success - Function, optional, callback function 257 | error - Function, optional, callback function if exists any error 258 | */ 259 | function printFile(parameters){ 260 | var filename, 261 | docname, 262 | printer, 263 | options, 264 | success, 265 | error; 266 | 267 | if((arguments.length !== 1) || (typeof(parameters) !== 'object')){ 268 | throw new Error('must provide arguments object'); 269 | } 270 | 271 | filename = parameters.filename; 272 | docname = parameters.docname; 273 | printer = parameters.printer; 274 | options = parameters.options || {}; 275 | success = parameters.success; 276 | error = parameters.error; 277 | 278 | if(!success){ 279 | success = function(){}; 280 | } 281 | 282 | if(!error){ 283 | error = function(err){ 284 | throw err; 285 | }; 286 | } 287 | 288 | if(!filename){ 289 | var err = new Error('must provide at least a filename'); 290 | return error(err); 291 | } 292 | 293 | // try to define default printer name 294 | if(!printer) { 295 | printer = getDefaultPrinterName(); 296 | } 297 | 298 | if(!printer) { 299 | return error(new Error('Printer parameter of default printer is not defined')); 300 | } 301 | 302 | // set filename if docname is missing 303 | if(!docname){ 304 | docname = filename; 305 | } 306 | 307 | //TODO: check parameters type 308 | if(printer_helper.printFile){// call C++ binding 309 | try{ 310 | // TODO: proper success/error callbacks from the extension 311 | var res = printer_helper.printFile(filename, docname, printer, options); 312 | 313 | if(!isNaN(parseInt(res))) { 314 | success(res); 315 | } else { 316 | error(Error(res)); 317 | } 318 | } catch (e) { 319 | error(e); 320 | } 321 | } else { 322 | error("Not supported"); 323 | } 324 | } 325 | -------------------------------------------------------------------------------- /node_modules/printer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_from": "printer@^0.2.2", 3 | "_id": "printer@0.2.2", 4 | "_inBundle": false, 5 | "_integrity": "sha1-gwuPXJe5f9m0ZNT04QXUMzd5IpY=", 6 | "_location": "/printer", 7 | "_phantomChildren": {}, 8 | "_requested": { 9 | "type": "range", 10 | "registry": true, 11 | "raw": "printer@^0.2.2", 12 | "name": "printer", 13 | "escapedName": "printer", 14 | "rawSpec": "^0.2.2", 15 | "saveSpec": null, 16 | "fetchSpec": "^0.2.2" 17 | }, 18 | "_requiredBy": [ 19 | "#USER", 20 | "/" 21 | ], 22 | "_resolved": "https://registry.npmjs.org/printer/-/printer-0.2.2.tgz", 23 | "_shasum": "830b8f5c97b97fd9b464d4f4e105d43337792296", 24 | "_spec": "printer@^0.2.2", 25 | "_where": "C:\\Users\\Sf\\Desktop\\app", 26 | "author": { 27 | "name": "Ion Lupascu", 28 | "email": "ionlupascu@gmail.com", 29 | "url": "http://program-support.co.uk/" 30 | }, 31 | "bugs": { 32 | "url": "https://github.com/tojocky/node-printer/issues" 33 | }, 34 | "bundleDependencies": false, 35 | "contributors": [ 36 | { 37 | "name": "Name Lastname", 38 | "email": "email@server.com" 39 | } 40 | ], 41 | "deprecated": false, 42 | "description": "Node.js printer bindings", 43 | "devDependencies": { 44 | "grunt": "^0.4.5", 45 | "grunt-contrib-copy": "^0.8.0", 46 | "grunt-contrib-jshint": "^0.11.0", 47 | "grunt-node-gyp": "git://github.com/tojocky/grunt-node-gyp.git", 48 | "grunt-nw-gyp": "git://github.com/tojocky/grunt-nw-gyp.git", 49 | "nodeunit": "*" 50 | }, 51 | "engines": { 52 | "node": ">= 0.8.0" 53 | }, 54 | "gypfile": true, 55 | "homepage": "http://github.com/tojocky/node-printer", 56 | "licenses": [ 57 | { 58 | "type": "BSD" 59 | } 60 | ], 61 | "main": "./lib/printer", 62 | "name": "printer", 63 | "repository": { 64 | "type": "git", 65 | "url": "git://github.com/tojocky/node-printer.git" 66 | }, 67 | "scripts": { 68 | "install": "node-gyp rebuild" 69 | }, 70 | "version": "0.2.2" 71 | } 72 | -------------------------------------------------------------------------------- /node_modules/printer/printer.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/printer'); -------------------------------------------------------------------------------- /node_modules/printer/src/macros.hh: -------------------------------------------------------------------------------- 1 | #ifndef NODE_PRINTER_SRC_MACROS_H 2 | #define NODE_PRINTER_SRC_MACROS_H 3 | 4 | #include 5 | 6 | // NODE_MODULE_VERSION was incremented for v0.11 7 | 8 | 9 | #if NODE_VERSION_AT_LEAST(0, 11, 9) 10 | # define MY_NODE_MODULE_ISOLATE_DECL v8::Isolate* isolate = v8::Isolate::GetCurrent(); 11 | # define MY_NODE_MODULE_ISOLATE isolate 12 | # define MY_NODE_MODULE_ISOLATE_PRE isolate, 13 | # define MY_NODE_MODULE_ISOLATE_POST , isolate 14 | # define MY_NODE_MODULE_HANDLESCOPE MY_NODE_MODULE_ISOLATE_DECL v8::HandleScope scope(MY_NODE_MODULE_ISOLATE) 15 | # define MY_NODE_MODULE_CALLBACK(name) void name(const v8::FunctionCallbackInfo& iArgs) 16 | # define V8_VALUE_NEW(type, value) v8::type::New(MY_NODE_MODULE_ISOLATE_PRE value) 17 | # define V8_VALUE_NEW_DEFAULT(type) v8::type::New(MY_NODE_MODULE_ISOLATE) 18 | # define V8_STRING_NEW_UTF8(value) v8::String::NewFromUtf8(MY_NODE_MODULE_ISOLATE_PRE value) 19 | # define V8_STRING_NEW_2BYTES(value) v8::String::NewFromTwoByte(MY_NODE_MODULE_ISOLATE_PRE value) 20 | 21 | # define RETURN_EXCEPTION(msg) isolate->ThrowException(v8::Exception::TypeError(msg)); \ 22 | return 23 | 24 | # define RETURN_EXCEPTION_STR(msg) RETURN_EXCEPTION(V8_STRING_NEW_UTF8(msg)) 25 | # define MY_NODE_MODULE_RETURN_VALUE(value) iArgs.GetReturnValue().Set(value); \ 26 | return 27 | # define MY_NODE_MODULE_RETURN_UNDEFINED() return 28 | #else 29 | # define MY_NODE_MODULE_ISOLATE_DECL 30 | # define MY_NODE_MODULE_ISOLATE 31 | # define MY_NODE_MODULE_ISOLATE_PRE 32 | # define MY_NODE_MODULE_ISOLATE_POST 33 | # define MY_NODE_MODULE_HANDLESCOPE v8::HandleScope scope; 34 | # define MY_NODE_MODULE_CALLBACK(name) v8::Handle name(const v8::Arguments& iArgs) 35 | # define V8_VALUE_NEW(type, value) v8::type::New(value) 36 | # define V8_VALUE_NEW_DEFAULT(type) v8::type::New() 37 | # define V8_STRING_NEW_UTF8(value) v8::String::New(MY_NODE_MODULE_ISOLATE_PRE value) 38 | # define V8_STRING_NEW_2BYTES(value) v8::String::New(MY_NODE_MODULE_ISOLATE_PRE value) 39 | 40 | # define RETURN_EXCEPTION(msg) return v8::ThrowException(v8::Exception::TypeError(msg)) 41 | 42 | # define RETURN_EXCEPTION_STR(msg) RETURN_EXCEPTION(V8_STRING_NEW_UTF8(msg)) 43 | # define MY_NODE_MODULE_RETURN_VALUE(value) return scope.Close(value) 44 | # define MY_NODE_MODULE_RETURN_UNDEFINED() return scope.Close(v8::Undefined()) 45 | #endif 46 | 47 | #if NODE_VERSION_AT_LEAST(0, 11, 10) // for node-webkit v.0.9.2 which uses node v0.11.9 48 | # define V8_VALUE_NEW_V_0_11_10(type, value) v8::type::New(MY_NODE_MODULE_ISOLATE_PRE value) 49 | # define V8_VALUE_NEW_DEFAULT_V_0_11_10(type) v8::type::New(MY_NODE_MODULE_ISOLATE) 50 | #else 51 | # define V8_VALUE_NEW_V_0_11_10(type, value) v8::type::New(value) 52 | # define V8_VALUE_NEW_DEFAULT_V_0_11_10(type) v8::type::New() 53 | #endif 54 | 55 | 56 | #define V8_STR_CONC(left, right) \ 57 | v8::String::Concat(V8_STRING_NEW_UTF8(left), V8_STRING_NEW_UTF8(right)) 58 | 59 | #define REQUIRE_ARGUMENTS(args, n) \ 60 | if (args.Length() < (n)) { \ 61 | RETURN_EXCEPTION_STR("Expected " #n " arguments"); \ 62 | } 63 | 64 | 65 | #define REQUIRE_ARGUMENT_EXTERNAL(i, var) \ 66 | if (args.Length() <= (i) || !args[i]->IsExternal()) { \ 67 | RETURN_EXCEPTION_STR("Argument " #i " invalid"); \ 68 | } \ 69 | v8::Local var = v8::Local::Cast(args[i]); 70 | 71 | #define REQUIRE_ARGUMENT_OBJECT(args, i, var) \ 72 | if (args.Length() <= (i) || !args[i]->IsObject()) { \ 73 | RETURN_EXCEPTION_STR("Argument " #i " is not an object"); \ 74 | } \ 75 | v8::Local var = v8::Local::Cast(args[i]); 76 | 77 | 78 | #define REQUIRE_ARGUMENT_FUNCTION(i, var) \ 79 | if (args.Length() <= (i) || !args[i]->IsFunction()) { \ 80 | RETURN_EXCEPTION_STR("Argument " #i " must be a function"); \ 81 | } \ 82 | v8::Local var = v8::Local::Cast(args[i]); 83 | 84 | 85 | #define ARG_CHECK_STRING(args, i) \ 86 | if (args.Length() <= (i) || !args[i]->IsString()) { \ 87 | RETURN_EXCEPTION_STR("Argument " #i " must be a string"); \ 88 | } \ 89 | 90 | #define REQUIRE_ARGUMENT_STRING(args, i, var) \ 91 | ARG_CHECK_STRING(args, i); \ 92 | v8::String::Utf8Value var(args[i]->ToString()); 93 | 94 | #define REQUIRE_ARGUMENT_STRINGW(args, i, var) \ 95 | ARG_CHECK_STRING(args, i); \ 96 | v8::String::Value var(args[i]->ToString()); 97 | 98 | 99 | #define OPTIONAL_ARGUMENT_FUNCTION(i, var) \ 100 | v8::Local var; \ 101 | if (args.Length() > i && !args[i]->IsUndefined()) { \ 102 | if (!args[i]->IsFunction()) { \ 103 | RETURN_EXCEPTION_STR("Argument " #i " must be a function"); \ 104 | } \ 105 | var = v8::Local::Cast(args[i]); \ 106 | } 107 | 108 | 109 | #define REQUIRE_ARGUMENT_INTEGER(args, i, var) \ 110 | int var; \ 111 | if (args[i]->IsInt32()) { \ 112 | var = args[i]->Int32Value(); \ 113 | } \ 114 | else { \ 115 | RETURN_EXCEPTION_STR("Argument " #i " must be an integer"); \ 116 | } 117 | 118 | #define OPTIONAL_ARGUMENT_INTEGER(args, i, var, default) \ 119 | int var; \ 120 | if (args.Length() <= (i)) { \ 121 | var = (default); \ 122 | } \ 123 | else if (args[i]->IsInt32()) { \ 124 | var = args[i]->Int32Value(); \ 125 | } \ 126 | else { \ 127 | RETURN_EXCEPTION_STR("Argument " #i " must be an integer"); \ 128 | } 129 | #define EMIT_EVENT(obj, argc, argv) \ 130 | TRY_CATCH_CALL((obj), \ 131 | Local::Cast((obj)->Get(String::NewSymbol("emit"))), \ 132 | argc, argv \ 133 | ); 134 | 135 | #define TRY_CATCH_CALL(context, callback, argc, argv) \ 136 | { TryCatch try_catch; \ 137 | (callback)->Call((context), (argc), (argv)); \ 138 | if (try_catch.HasCaught()) { \ 139 | FatalException(try_catch); \ 140 | } \ 141 | } 142 | 143 | #endif 144 | -------------------------------------------------------------------------------- /node_modules/printer/src/node_printer.cc: -------------------------------------------------------------------------------- 1 | #include "node_printer.hpp" 2 | 3 | #include 4 | 5 | void initNode(v8::Handle exports) { 6 | // only for node 7 | NODE_SET_METHOD(exports, "getPrinters", getPrinters); 8 | NODE_SET_METHOD(exports, "getDefaultPrinterName", getDefaultPrinterName); 9 | NODE_SET_METHOD(exports, "getPrinter", getPrinter); 10 | NODE_SET_METHOD(exports, "getPrinterDriverOptions", getPrinterDriverOptions); 11 | NODE_SET_METHOD(exports, "getJob", getJob); 12 | NODE_SET_METHOD(exports, "setJob", setJob); 13 | NODE_SET_METHOD(exports, "printDirect", PrintDirect); 14 | NODE_SET_METHOD(exports, "printFile", PrintFile); 15 | NODE_SET_METHOD(exports, "getSupportedPrintFormats", getSupportedPrintFormats); 16 | NODE_SET_METHOD(exports, "getSupportedJobCommands", getSupportedJobCommands); 17 | } 18 | 19 | NODE_MODULE(node_printer, initNode); 20 | 21 | // Helpers 22 | 23 | bool getStringOrBufferFromV8Value(v8::Handle iV8Value, std::string &oData) 24 | { 25 | if(iV8Value->IsString()) 26 | { 27 | v8::String::Utf8Value data_str_v8(iV8Value->ToString()); 28 | oData.assign(*data_str_v8, data_str_v8.length()); 29 | return true; 30 | } 31 | if(iV8Value->IsObject() && node::Buffer::HasInstance(iV8Value)) 32 | { 33 | oData.assign(node::Buffer::Data(iV8Value), node::Buffer::Length(iV8Value)); 34 | return true; 35 | } 36 | return false; 37 | } 38 | -------------------------------------------------------------------------------- /node_modules/printer/src/node_printer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef NODE_PRINTER_HPP 2 | #define NODE_PRINTER_HPP 3 | 4 | #include "macros.hh" 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | /** 12 | * Send data to printer 13 | * 14 | * @param data String/NativeBuffer, mandatory, raw data bytes 15 | * @param printername String, mandatory, specifying printer name 16 | * @param docname String, mandatory, specifying document name 17 | * @param type String, mandatory, specifying data type. E.G.: RAW, TEXT, ... 18 | * 19 | * @returns true for success, false for failure. 20 | */ 21 | MY_NODE_MODULE_CALLBACK(PrintDirect); 22 | 23 | /** 24 | * Send file to printer 25 | * 26 | * @param filename String, mandatory, specifying filename to print 27 | * @param docname String, mandatory, specifying document name 28 | * @param printer String, mandatory, specifying printer name 29 | * 30 | * @returns jobId for success, or error message for failure. 31 | */ 32 | MY_NODE_MODULE_CALLBACK(PrintFile); 33 | 34 | /** Retrieve all printers and jobs 35 | * posix: minimum version: CUPS 1.1.21/OS X 10.4 36 | */ 37 | MY_NODE_MODULE_CALLBACK(getPrinters); 38 | 39 | /** 40 | * Return default printer name, if null then default printer is not set 41 | */ 42 | MY_NODE_MODULE_CALLBACK(getDefaultPrinterName); 43 | 44 | /** Retrieve printer info and jobs 45 | * @param printer name String 46 | */ 47 | MY_NODE_MODULE_CALLBACK(getPrinter); 48 | 49 | /** Retrieve printer driver info 50 | * @param printer name String 51 | */ 52 | MY_NODE_MODULE_CALLBACK(getPrinterDriverOptions); 53 | 54 | /** Retrieve job info 55 | * @param printer name String 56 | * @param job id Number 57 | */ 58 | MY_NODE_MODULE_CALLBACK(getJob); 59 | 60 | //TODO 61 | /** Set job command. 62 | * arguments: 63 | * @param printer name String 64 | * @param job id Number 65 | * @param job command String 66 | * Possible commands: 67 | * "CANCEL" 68 | * "PAUSE" 69 | * "RESTART" 70 | * "RESUME" 71 | * "DELETE" 72 | * "SENT-TO-PRINTER" 73 | * "LAST-PAGE-EJECTED" 74 | * "RETAIN" 75 | * "RELEASE" 76 | */ 77 | MY_NODE_MODULE_CALLBACK(setJob); 78 | 79 | /** Get supported print formats for printDirect. It depends on platform 80 | */ 81 | MY_NODE_MODULE_CALLBACK(getSupportedPrintFormats); 82 | 83 | /** Get supported job commands for setJob method 84 | */ 85 | MY_NODE_MODULE_CALLBACK(getSupportedJobCommands); 86 | 87 | //TODO: 88 | // optional ability to get printer spool 89 | 90 | 91 | // util class 92 | 93 | /** Memory value class management to avoid memory leak 94 | * TODO: move to std::unique_ptr on switching to C++11 95 | */ 96 | template 97 | class MemValueBase 98 | { 99 | public: 100 | MemValueBase(): _value(NULL) {} 101 | 102 | /** Destructor. The allocated memory will be deallocated 103 | */ 104 | ~MemValueBase() {} 105 | 106 | Type * get() {return _value; } 107 | Type * operator ->() { return &_value; } 108 | operator bool() const { return (_value != NULL); } 109 | protected: 110 | Type *_value; 111 | 112 | virtual void free() {}; 113 | }; 114 | 115 | /** 116 | * try to extract String or buffer from v8 value 117 | * @param iV8Value - source v8 value 118 | * @param oData - destination data 119 | * @return TRUE if value is String or Buffer, FALSE otherwise 120 | */ 121 | bool getStringOrBufferFromV8Value(v8::Handle iV8Value, std::string &oData); 122 | 123 | #endif 124 | -------------------------------------------------------------------------------- /node_modules/printer/src/node_printer_posix.cc: -------------------------------------------------------------------------------- 1 | #include "node_printer.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | namespace 13 | { 14 | typedef std::map StatusMapType; 15 | typedef std::map FormatMapType; 16 | 17 | const StatusMapType& getJobStatusMap() 18 | { 19 | static StatusMapType result; 20 | if(!result.empty()) 21 | { 22 | return result; 23 | } 24 | // add only first time 25 | #define STATUS_PRINTER_ADD(value, type) result.insert(std::make_pair(value, type)) 26 | // Common statuses 27 | STATUS_PRINTER_ADD("PRINTING", IPP_JOB_PROCESSING); 28 | STATUS_PRINTER_ADD("PRINTED", IPP_JOB_COMPLETED); 29 | STATUS_PRINTER_ADD("PAUSED", IPP_JOB_HELD); 30 | // Specific statuses 31 | STATUS_PRINTER_ADD("PENDING", IPP_JOB_PENDING); 32 | STATUS_PRINTER_ADD("PAUSED", IPP_JOB_STOPPED); 33 | STATUS_PRINTER_ADD("CANCELLED", IPP_JOB_CANCELLED); 34 | STATUS_PRINTER_ADD("ABORTED", IPP_JOB_ABORTED); 35 | 36 | #undef STATUS_PRINTER_ADD 37 | return result; 38 | } 39 | 40 | const FormatMapType& getPrinterFormatMap() 41 | { 42 | static FormatMapType result; 43 | if(!result.empty()) 44 | { 45 | return result; 46 | } 47 | result.insert(std::make_pair("RAW", CUPS_FORMAT_RAW)); 48 | result.insert(std::make_pair("TEXT", CUPS_FORMAT_TEXT)); 49 | #ifdef CUPS_FORMAT_PDF 50 | result.insert(std::make_pair("PDF", CUPS_FORMAT_PDF)); 51 | #endif 52 | #ifdef CUPS_FORMAT_JPEG 53 | result.insert(std::make_pair("JPEG", CUPS_FORMAT_JPEG)); 54 | #endif 55 | #ifdef CUPS_FORMAT_POSTSCRIPT 56 | result.insert(std::make_pair("POSTSCRIPT", CUPS_FORMAT_POSTSCRIPT)); 57 | #endif 58 | #ifdef CUPS_FORMAT_COMMAND 59 | result.insert(std::make_pair("COMMAND", CUPS_FORMAT_COMMAND)); 60 | #endif 61 | #ifdef CUPS_FORMAT_AUTO 62 | result.insert(std::make_pair("AUTO", CUPS_FORMAT_AUTO)); 63 | #endif 64 | return result; 65 | } 66 | 67 | /** Parse job info object. 68 | * @return error string. if empty, then no error 69 | */ 70 | std::string parseJobObject(const cups_job_t *job, v8::Handle result_printer_job) 71 | { 72 | MY_NODE_MODULE_ISOLATE_DECL 73 | //Common fields 74 | result_printer_job->Set(V8_STRING_NEW_UTF8("id"), V8_VALUE_NEW(Number, job->id)); 75 | result_printer_job->Set(V8_STRING_NEW_UTF8("name"), V8_STRING_NEW_UTF8(job->title)); 76 | result_printer_job->Set(V8_STRING_NEW_UTF8("printerName"), V8_STRING_NEW_UTF8(job->dest)); 77 | result_printer_job->Set(V8_STRING_NEW_UTF8("user"), V8_STRING_NEW_UTF8(job->user)); 78 | std::string job_format(job->format); 79 | 80 | // Try to parse the data format, otherwise will write the unformatted one 81 | for(FormatMapType::const_iterator itFormat = getPrinterFormatMap().begin(); itFormat != getPrinterFormatMap().end(); ++itFormat) 82 | { 83 | if(itFormat->second == job_format) 84 | { 85 | job_format = itFormat->first; 86 | break; 87 | } 88 | } 89 | 90 | result_printer_job->Set(V8_STRING_NEW_UTF8("format"), V8_STRING_NEW_UTF8(job_format.c_str())); 91 | result_printer_job->Set(V8_STRING_NEW_UTF8("priority"), V8_VALUE_NEW(Number, job->priority)); 92 | result_printer_job->Set(V8_STRING_NEW_UTF8("size"), V8_VALUE_NEW(Number, job->size)); 93 | v8::Local result_printer_job_status = V8_VALUE_NEW_DEFAULT_V_0_11_10(Array); 94 | int i_status = 0; 95 | for(StatusMapType::const_iterator itStatus = getJobStatusMap().begin(); itStatus != getJobStatusMap().end(); ++itStatus) 96 | { 97 | if(job->state == itStatus->second) 98 | { 99 | result_printer_job_status->Set(i_status++, V8_STRING_NEW_UTF8(itStatus->first.c_str())); 100 | // only one status could be on posix 101 | break; 102 | } 103 | } 104 | if(i_status == 0) 105 | { 106 | // A new status? report as unsupported 107 | std::ostringstream s; 108 | s << "unsupported job status: " << job->state; 109 | result_printer_job_status->Set(i_status++, V8_STRING_NEW_UTF8(s.str().c_str())); 110 | } 111 | 112 | result_printer_job->Set(V8_STRING_NEW_UTF8("status"), result_printer_job_status); 113 | 114 | //Specific fields 115 | // Ecmascript store time in milliseconds, but time_t in seconds 116 | result_printer_job->Set(V8_STRING_NEW_UTF8("completedTime"), V8_VALUE_NEW(Date, job->completed_time*1000)); 117 | result_printer_job->Set(V8_STRING_NEW_UTF8("creationTime"), V8_VALUE_NEW(Date, job->creation_time*1000)); 118 | result_printer_job->Set(V8_STRING_NEW_UTF8("processingTime"), V8_VALUE_NEW(Date, job->processing_time*1000)); 119 | 120 | // No error. return an empty string 121 | return ""; 122 | } 123 | 124 | /** Parses printer driver PPD options 125 | */ 126 | void populatePpdOptions(v8::Handle ppd_options, ppd_file_t *ppd, ppd_group_t *group) 127 | { 128 | int i, j; 129 | ppd_option_t *option; 130 | ppd_choice_t *choice; 131 | ppd_group_t *subgroup; 132 | 133 | for (i = group->num_options, option = group->options; i > 0; --i, ++option) 134 | { 135 | MY_NODE_MODULE_ISOLATE_DECL 136 | v8::Local ppd_suboptions = V8_VALUE_NEW_DEFAULT_V_0_11_10(Object); 137 | for (j = option->num_choices, choice = option->choices; 138 | j > 0; 139 | --j, ++choice) 140 | { 141 | ppd_suboptions->Set(V8_STRING_NEW_UTF8(choice->choice), V8_VALUE_NEW_V_0_11_10(Boolean, static_cast(choice->marked))); 142 | } 143 | 144 | ppd_options->Set(V8_STRING_NEW_UTF8(option->keyword), ppd_suboptions); 145 | } 146 | 147 | for (i = group->num_subgroups, subgroup = group->subgroups; i > 0; --i, ++subgroup) { 148 | populatePpdOptions(ppd_options, ppd, subgroup); 149 | } 150 | } 151 | 152 | /** Parse printer driver options 153 | * @return error string. 154 | */ 155 | std::string parseDriverOptions(const cups_dest_t * printer, v8::Handle ppd_options) 156 | { 157 | const char *filename; 158 | ppd_file_t *ppd; 159 | ppd_group_t *group; 160 | int i; 161 | 162 | std::ostringstream error_str; // error string 163 | 164 | if ((filename = cupsGetPPD(printer->name)) != NULL) 165 | { 166 | if ((ppd = ppdOpenFile(filename)) != NULL) 167 | { 168 | ppdMarkDefaults(ppd); 169 | cupsMarkOptions(ppd, printer->num_options, printer->options); 170 | 171 | for (i = ppd->num_groups, group = ppd->groups; i > 0; --i, ++group) 172 | { 173 | populatePpdOptions(ppd_options, ppd, group); 174 | } 175 | ppdClose(ppd); 176 | } 177 | else 178 | { 179 | error_str << "Unable to open PPD filename " << filename << " "; 180 | } 181 | unlink(filename); 182 | } 183 | else 184 | { 185 | error_str << "Unable to get CUPS PPD driver file. "; 186 | } 187 | 188 | return error_str.str(); 189 | } 190 | 191 | 192 | /** Parse printer info object 193 | * @return error string. 194 | */ 195 | std::string parsePrinterInfo(const cups_dest_t * printer, v8::Handle result_printer) 196 | { 197 | MY_NODE_MODULE_ISOLATE_DECL 198 | result_printer->Set(V8_STRING_NEW_UTF8("name"), V8_STRING_NEW_UTF8(printer->name)); 199 | result_printer->Set(V8_STRING_NEW_UTF8("isDefault"), V8_VALUE_NEW_V_0_11_10(Boolean, static_cast(printer->is_default))); 200 | 201 | if(printer->instance) 202 | { 203 | result_printer->Set(V8_STRING_NEW_UTF8("instance"), V8_STRING_NEW_UTF8(printer->instance)); 204 | } 205 | 206 | v8::Local result_printer_options = V8_VALUE_NEW_DEFAULT_V_0_11_10(Object); 207 | cups_option_t *dest_option = printer->options; 208 | for(int j = 0; j < printer->num_options; ++j, ++dest_option) 209 | { 210 | result_printer_options->Set(V8_STRING_NEW_UTF8(dest_option->name), V8_STRING_NEW_UTF8(dest_option->value)); 211 | } 212 | result_printer->Set(V8_STRING_NEW_UTF8("options"), result_printer_options); 213 | // Get printer jobs 214 | cups_job_t * jobs; 215 | int totalJobs = cupsGetJobs(&jobs, printer->name, 0 /*0 means all users*/, CUPS_WHICHJOBS_ACTIVE); 216 | std::string error_str; 217 | if(totalJobs > 0) 218 | { 219 | v8::Local result_priner_jobs = V8_VALUE_NEW_V_0_11_10(Array, totalJobs); 220 | int jobi =0; 221 | cups_job_t * job = jobs; 222 | for(; jobi < totalJobs; ++jobi, ++job) 223 | { 224 | v8::Local result_printer_job = V8_VALUE_NEW_DEFAULT_V_0_11_10(Object); 225 | error_str = parseJobObject(job, result_printer_job); 226 | if(!error_str.empty()) 227 | { 228 | // got an error? break then. 229 | break; 230 | } 231 | result_priner_jobs->Set(jobi, result_printer_job); 232 | } 233 | result_printer->Set(V8_STRING_NEW_UTF8("jobs"), result_priner_jobs); 234 | } 235 | cupsFreeJobs(totalJobs, jobs); 236 | return error_str; 237 | } 238 | 239 | /// cups option class to automatically free memory. 240 | class CupsOptions: public MemValueBase { 241 | protected: 242 | int num_options; 243 | virtual void free() { 244 | if(_value != NULL) 245 | { 246 | cupsFreeOptions(num_options, get()); 247 | _value = NULL; 248 | num_options = 0; 249 | } 250 | } 251 | public: 252 | CupsOptions(): num_options(0) {} 253 | ~CupsOptions () { free(); } 254 | 255 | /// Add options from v8 object 256 | CupsOptions(v8::Local iV8Options): num_options(0) { 257 | v8::Local props = iV8Options->GetPropertyNames(); 258 | 259 | for(unsigned int i = 0; i < props->Length(); ++i) { 260 | v8::Handle key(props->Get(i)); 261 | v8::String::Utf8Value keyStr(key->ToString()); 262 | v8::String::Utf8Value valStr(iV8Options->Get(key)->ToString()); 263 | 264 | num_options = cupsAddOption(*keyStr, *valStr, num_options, &_value); 265 | } 266 | } 267 | 268 | const int& getNumOptions() { return num_options; } 269 | }; 270 | } 271 | 272 | MY_NODE_MODULE_CALLBACK(getPrinters) 273 | { 274 | MY_NODE_MODULE_HANDLESCOPE; 275 | 276 | cups_dest_t *printers = NULL; 277 | int printers_size = cupsGetDests(&printers); 278 | v8::Local result = V8_VALUE_NEW_V_0_11_10(Array, printers_size); 279 | cups_dest_t *printer = printers; 280 | std::string error_str; 281 | for(int i = 0; i < printers_size; ++i, ++printer) 282 | { 283 | v8::Local result_printer = V8_VALUE_NEW_DEFAULT_V_0_11_10(Object); 284 | error_str = parsePrinterInfo(printer, result_printer); 285 | if(!error_str.empty()) 286 | { 287 | // got an error? break then 288 | break; 289 | } 290 | result->Set(i, result_printer); 291 | } 292 | cupsFreeDests(printers_size, printers); 293 | if(!error_str.empty()) 294 | { 295 | // got an error? return the error then 296 | RETURN_EXCEPTION_STR(error_str.c_str()); 297 | } 298 | MY_NODE_MODULE_RETURN_VALUE(result); 299 | } 300 | 301 | MY_NODE_MODULE_CALLBACK(getDefaultPrinterName) 302 | { 303 | MY_NODE_MODULE_HANDLESCOPE; 304 | //This does not return default user printer name according to https://www.cups.org/documentation.php/doc-2.0/api-cups.html#cupsGetDefault2 305 | //so leave as undefined and JS implementation will loop in all printers 306 | /* 307 | const char * printerName = cupsGetDefault(); 308 | 309 | // return default printer name only if defined 310 | if(printerName != NULL) { 311 | MY_NODE_MODULE_RETURN_VALUE(V8_STRING_NEW_UTF8(printerName)); 312 | } 313 | */ 314 | MY_NODE_MODULE_RETURN_UNDEFINED(); 315 | } 316 | 317 | MY_NODE_MODULE_CALLBACK(getPrinter) 318 | { 319 | MY_NODE_MODULE_HANDLESCOPE; 320 | REQUIRE_ARGUMENTS(iArgs, 1); 321 | REQUIRE_ARGUMENT_STRING(iArgs, 0, printername); 322 | 323 | cups_dest_t *printers = NULL, *printer = NULL; 324 | int printers_size = cupsGetDests(&printers); 325 | printer = cupsGetDest(*printername, NULL, printers_size, printers); 326 | v8::Local result_printer = V8_VALUE_NEW_DEFAULT_V_0_11_10(Object); 327 | if(printer != NULL) 328 | { 329 | parsePrinterInfo(printer, result_printer); 330 | } 331 | cupsFreeDests(printers_size, printers); 332 | if(printer == NULL) 333 | { 334 | // printer not found 335 | RETURN_EXCEPTION_STR("Printer not found"); 336 | } 337 | MY_NODE_MODULE_RETURN_VALUE(result_printer); 338 | } 339 | 340 | MY_NODE_MODULE_CALLBACK(getPrinterDriverOptions) 341 | { 342 | MY_NODE_MODULE_HANDLESCOPE; 343 | REQUIRE_ARGUMENTS(iArgs, 1); 344 | REQUIRE_ARGUMENT_STRING(iArgs, 0, printername); 345 | 346 | cups_dest_t *printers = NULL, *printer = NULL; 347 | int printers_size = cupsGetDests(&printers); 348 | printer = cupsGetDest(*printername, NULL, printers_size, printers); 349 | v8::Local driver_options = V8_VALUE_NEW_DEFAULT_V_0_11_10(Object); 350 | if(printer != NULL) 351 | { 352 | parseDriverOptions(printer, driver_options); 353 | } 354 | cupsFreeDests(printers_size, printers); 355 | if(printer == NULL) 356 | { 357 | // printer not found 358 | RETURN_EXCEPTION_STR("Printer not found"); 359 | } 360 | MY_NODE_MODULE_RETURN_VALUE(driver_options); 361 | } 362 | 363 | MY_NODE_MODULE_CALLBACK(getJob) 364 | { 365 | MY_NODE_MODULE_HANDLESCOPE; 366 | REQUIRE_ARGUMENTS(iArgs, 2); 367 | REQUIRE_ARGUMENT_STRING(iArgs, 0, printername); 368 | REQUIRE_ARGUMENT_INTEGER(iArgs, 1, jobId); 369 | 370 | v8::Local result_printer_job = V8_VALUE_NEW_DEFAULT_V_0_11_10(Object); 371 | // Get printer jobs 372 | cups_job_t *jobs = NULL, *jobFound = NULL; 373 | int totalJobs = cupsGetJobs(&jobs, *printername, 0 /*0 means all users*/, CUPS_WHICHJOBS_ALL); 374 | if(totalJobs > 0) 375 | { 376 | int jobi =0; 377 | cups_job_t * job = jobs; 378 | for(; jobi < totalJobs; ++jobi, ++job) 379 | { 380 | if(job->id != jobId) 381 | { 382 | continue; 383 | } 384 | // Job Found 385 | jobFound = job; 386 | parseJobObject(job, result_printer_job); 387 | break; 388 | } 389 | } 390 | cupsFreeJobs(totalJobs, jobs); 391 | if(jobFound == NULL) 392 | { 393 | // printer not found 394 | RETURN_EXCEPTION_STR("Printer job not found"); 395 | } 396 | MY_NODE_MODULE_RETURN_VALUE(result_printer_job); 397 | } 398 | 399 | MY_NODE_MODULE_CALLBACK(setJob) 400 | { 401 | MY_NODE_MODULE_HANDLESCOPE; 402 | REQUIRE_ARGUMENTS(iArgs, 3); 403 | REQUIRE_ARGUMENT_STRING(iArgs, 0, printername); 404 | REQUIRE_ARGUMENT_INTEGER(iArgs, 1, jobId); 405 | REQUIRE_ARGUMENT_STRING(iArgs, 2, jobCommandV8); 406 | if(jobId < 0) 407 | { 408 | RETURN_EXCEPTION_STR("Wrong job number"); 409 | } 410 | std::string jobCommandStr(*jobCommandV8); 411 | bool result_ok = false; 412 | if(jobCommandStr == "CANCEL") 413 | { 414 | result_ok = (cupsCancelJob(*printername, jobId) == 1); 415 | } 416 | else 417 | { 418 | RETURN_EXCEPTION_STR("wrong job command. use getSupportedJobCommands to see the possible commands"); 419 | } 420 | MY_NODE_MODULE_RETURN_VALUE(V8_VALUE_NEW_V_0_11_10(Boolean, result_ok)); 421 | } 422 | 423 | MY_NODE_MODULE_CALLBACK(getSupportedJobCommands) 424 | { 425 | MY_NODE_MODULE_HANDLESCOPE; 426 | v8::Local result = V8_VALUE_NEW_DEFAULT_V_0_11_10(Array); 427 | int i = 0; 428 | result->Set(i++, V8_STRING_NEW_UTF8("CANCEL")); 429 | MY_NODE_MODULE_RETURN_VALUE(result); 430 | } 431 | 432 | MY_NODE_MODULE_CALLBACK(getSupportedPrintFormats) 433 | { 434 | MY_NODE_MODULE_HANDLESCOPE; 435 | v8::Local result = V8_VALUE_NEW_DEFAULT_V_0_11_10(Array); 436 | int i = 0; 437 | for(FormatMapType::const_iterator itFormat = getPrinterFormatMap().begin(); itFormat != getPrinterFormatMap().end(); ++itFormat) 438 | { 439 | result->Set(i++, V8_STRING_NEW_UTF8(itFormat->first.c_str())); 440 | } 441 | MY_NODE_MODULE_RETURN_VALUE(result); 442 | } 443 | 444 | MY_NODE_MODULE_CALLBACK(PrintDirect) 445 | { 446 | MY_NODE_MODULE_HANDLESCOPE; 447 | REQUIRE_ARGUMENTS(iArgs, 5); 448 | 449 | // can be string or buffer 450 | if(iArgs.Length() <= 0) 451 | { 452 | RETURN_EXCEPTION_STR("Argument 0 missing"); 453 | } 454 | 455 | std::string data; 456 | v8::Handle arg0(iArgs[0]); 457 | if (!getStringOrBufferFromV8Value(arg0, data)) 458 | { 459 | RETURN_EXCEPTION_STR("Argument 0 must be a string or Buffer"); 460 | } 461 | 462 | REQUIRE_ARGUMENT_STRING(iArgs, 1, printername); 463 | REQUIRE_ARGUMENT_STRING(iArgs, 2, docname); 464 | REQUIRE_ARGUMENT_STRING(iArgs, 3, type); 465 | REQUIRE_ARGUMENT_OBJECT(iArgs, 4, print_options); 466 | 467 | std::string type_str(*type); 468 | FormatMapType::const_iterator itFormat = getPrinterFormatMap().find(type_str); 469 | if(itFormat == getPrinterFormatMap().end()) 470 | { 471 | RETURN_EXCEPTION_STR("unsupported format type"); 472 | } 473 | type_str = itFormat->second; 474 | 475 | CupsOptions options(print_options); 476 | 477 | int job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, *printername, *docname, options.getNumOptions(), options.get()); 478 | if(job_id == 0) { 479 | RETURN_EXCEPTION_STR(cupsLastErrorString()); 480 | } 481 | 482 | if(HTTP_CONTINUE != cupsStartDocument(CUPS_HTTP_DEFAULT, *printername, job_id, *docname, type_str.c_str(), 1 /*last document*/)) { 483 | RETURN_EXCEPTION_STR(cupsLastErrorString()); 484 | } 485 | 486 | /* cupsWriteRequestData can be called as many times as needed */ 487 | //TODO: to split big buffer 488 | if (HTTP_CONTINUE != cupsWriteRequestData(CUPS_HTTP_DEFAULT, data.c_str(), data.size())) { 489 | cupsFinishDocument(CUPS_HTTP_DEFAULT, *printername); 490 | RETURN_EXCEPTION_STR(cupsLastErrorString()); 491 | } 492 | 493 | cupsFinishDocument(CUPS_HTTP_DEFAULT, *printername); 494 | 495 | MY_NODE_MODULE_RETURN_VALUE(V8_VALUE_NEW(Number, job_id)); 496 | } 497 | 498 | MY_NODE_MODULE_CALLBACK(PrintFile) 499 | { 500 | MY_NODE_MODULE_HANDLESCOPE; 501 | REQUIRE_ARGUMENTS(iArgs, 3); 502 | 503 | // can be string or buffer 504 | if(iArgs.Length() <= 0) 505 | { 506 | RETURN_EXCEPTION_STR("Argument 0 missing"); 507 | } 508 | 509 | REQUIRE_ARGUMENT_STRING(iArgs, 0, filename); 510 | REQUIRE_ARGUMENT_STRING(iArgs, 1, docname); 511 | REQUIRE_ARGUMENT_STRING(iArgs, 2, printer); 512 | REQUIRE_ARGUMENT_OBJECT(iArgs, 3, print_options); 513 | 514 | CupsOptions options(print_options); 515 | 516 | int job_id = cupsPrintFile(*printer, *filename, *docname, options.getNumOptions(), options.get()); 517 | 518 | if(job_id == 0){ 519 | MY_NODE_MODULE_RETURN_VALUE(V8_STRING_NEW_UTF8(cupsLastErrorString())); 520 | } else { 521 | MY_NODE_MODULE_RETURN_VALUE(V8_VALUE_NEW(Number, job_id)); 522 | } 523 | } 524 | -------------------------------------------------------------------------------- /node_modules/printer/src/node_printer_win.cc: -------------------------------------------------------------------------------- 1 | #include "node_printer.hpp" 2 | 3 | #if _MSC_VER 4 | #include 5 | #include 6 | #include 7 | #pragma comment(lib, "Winspool.lib") 8 | #else 9 | #error "Unsupported compiler for windows. Feel free to add it." 10 | #endif 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace{ 19 | typedef std::map StatusMapType; 20 | 21 | /** Memory value class management to avoid memory leak 22 | */ 23 | template 24 | class MemValue: public MemValueBase { 25 | public: 26 | /** Constructor of allocating iSizeKbytes bytes memory; 27 | * @param iSizeKbytes size in bytes of required allocating memory 28 | */ 29 | MemValue(const DWORD iSizeKbytes) { 30 | _value = (Type*)malloc(iSizeKbytes); 31 | } 32 | 33 | ~MemValue () { 34 | free(); 35 | } 36 | protected: 37 | virtual void free() { 38 | if(_value != NULL) 39 | { 40 | ::free(_value); 41 | _value = NULL; 42 | } 43 | } 44 | }; 45 | 46 | struct PrinterHandle 47 | { 48 | PrinterHandle(LPWSTR iPrinterName) 49 | { 50 | _ok = OpenPrinterW(iPrinterName, &_printer, NULL); 51 | } 52 | ~PrinterHandle() 53 | { 54 | if(_ok) 55 | { 56 | ClosePrinter(_printer); 57 | } 58 | } 59 | operator HANDLE() {return _printer;} 60 | operator bool() { return (!!_ok);} 61 | HANDLE & operator *() { return _printer;} 62 | HANDLE * operator ->() { return &_printer;} 63 | const HANDLE & operator ->() const { return _printer;} 64 | HANDLE _printer; 65 | BOOL _ok; 66 | }; 67 | 68 | const StatusMapType& getStatusMap() 69 | { 70 | static StatusMapType result; 71 | if(!result.empty()) 72 | { 73 | return result; 74 | } 75 | // add only first time 76 | #define STATUS_PRINTER_ADD(value, type) result.insert(std::make_pair(value, type)) 77 | STATUS_PRINTER_ADD("BUSY", PRINTER_STATUS_BUSY); 78 | STATUS_PRINTER_ADD("DOOR-OPEN", PRINTER_STATUS_DOOR_OPEN); 79 | STATUS_PRINTER_ADD("ERROR", PRINTER_STATUS_ERROR); 80 | STATUS_PRINTER_ADD("INITIALIZING", PRINTER_STATUS_INITIALIZING); 81 | STATUS_PRINTER_ADD("IO-ACTIVE", PRINTER_STATUS_IO_ACTIVE); 82 | STATUS_PRINTER_ADD("MANUAL-FEED", PRINTER_STATUS_MANUAL_FEED); 83 | STATUS_PRINTER_ADD("NO-TONER", PRINTER_STATUS_NO_TONER); 84 | STATUS_PRINTER_ADD("NOT-AVAILABLE", PRINTER_STATUS_NOT_AVAILABLE); 85 | STATUS_PRINTER_ADD("OFFLINE", PRINTER_STATUS_OFFLINE); 86 | STATUS_PRINTER_ADD("OUT-OF-MEMORY", PRINTER_STATUS_OUT_OF_MEMORY); 87 | STATUS_PRINTER_ADD("OUTPUT-BIN-FULL", PRINTER_STATUS_OUTPUT_BIN_FULL); 88 | STATUS_PRINTER_ADD("PAGE-PUNT", PRINTER_STATUS_PAGE_PUNT); 89 | STATUS_PRINTER_ADD("PAPER-JAM", PRINTER_STATUS_PAPER_JAM); 90 | STATUS_PRINTER_ADD("PAPER-OUT", PRINTER_STATUS_PAPER_OUT); 91 | STATUS_PRINTER_ADD("PAPER-PROBLEM", PRINTER_STATUS_PAPER_PROBLEM); 92 | STATUS_PRINTER_ADD("PAUSED", PRINTER_STATUS_PAUSED); 93 | STATUS_PRINTER_ADD("PENDING-DELETION", PRINTER_STATUS_PENDING_DELETION); 94 | STATUS_PRINTER_ADD("POWER-SAVE", PRINTER_STATUS_POWER_SAVE); 95 | STATUS_PRINTER_ADD("PRINTING", PRINTER_STATUS_PRINTING); 96 | STATUS_PRINTER_ADD("PROCESSING", PRINTER_STATUS_PROCESSING); 97 | STATUS_PRINTER_ADD("SERVER-UNKNOWN", PRINTER_STATUS_SERVER_UNKNOWN); 98 | STATUS_PRINTER_ADD("TONER-LOW", PRINTER_STATUS_TONER_LOW); 99 | STATUS_PRINTER_ADD("USER-INTERVENTION", PRINTER_STATUS_USER_INTERVENTION); 100 | STATUS_PRINTER_ADD("WAITING", PRINTER_STATUS_WAITING); 101 | STATUS_PRINTER_ADD("WARMING-UP", PRINTER_STATUS_WARMING_UP); 102 | #undef STATUS_PRINTER_ADD 103 | return result; 104 | } 105 | 106 | const StatusMapType& getJobStatusMap() 107 | { 108 | static StatusMapType result; 109 | if(!result.empty()) 110 | { 111 | return result; 112 | } 113 | // add only first time 114 | #define STATUS_PRINTER_ADD(value, type) result.insert(std::make_pair(value, type)) 115 | // Common statuses 116 | STATUS_PRINTER_ADD("PRINTING", JOB_STATUS_PRINTING); 117 | STATUS_PRINTER_ADD("PRINTED", JOB_STATUS_PRINTED); 118 | STATUS_PRINTER_ADD("PAUSED", JOB_STATUS_PAUSED); 119 | 120 | // Specific statuses 121 | STATUS_PRINTER_ADD("BLOCKED-DEVQ", JOB_STATUS_BLOCKED_DEVQ); 122 | STATUS_PRINTER_ADD("DELETED", JOB_STATUS_DELETED); 123 | STATUS_PRINTER_ADD("DELETING", JOB_STATUS_DELETING); 124 | STATUS_PRINTER_ADD("ERROR", JOB_STATUS_ERROR); 125 | STATUS_PRINTER_ADD("OFFLINE", JOB_STATUS_OFFLINE); 126 | STATUS_PRINTER_ADD("PAPEROUT", JOB_STATUS_PAPEROUT); 127 | STATUS_PRINTER_ADD("RESTART", JOB_STATUS_RESTART); 128 | STATUS_PRINTER_ADD("SPOOLING", JOB_STATUS_SPOOLING); 129 | STATUS_PRINTER_ADD("USER-INTERVENTION", JOB_STATUS_USER_INTERVENTION); 130 | // XP and later 131 | #ifdef JOB_STATUS_COMPLETE 132 | STATUS_PRINTER_ADD("COMPLETE", JOB_STATUS_COMPLETE); 133 | #endif 134 | #ifdef JOB_STATUS_RETAINED 135 | STATUS_PRINTER_ADD("RETAINED", JOB_STATUS_RETAINED); 136 | #endif 137 | 138 | #undef STATUS_PRINTER_ADD 139 | return result; 140 | } 141 | 142 | const StatusMapType& getAttributeMap() 143 | { 144 | static StatusMapType result; 145 | if(!result.empty()) 146 | { 147 | return result; 148 | } 149 | // add only first time 150 | #define ATTRIBUTE_PRINTER_ADD(value, type) result.insert(std::make_pair(value, type)) 151 | ATTRIBUTE_PRINTER_ADD("DIRECT", PRINTER_ATTRIBUTE_DIRECT); 152 | ATTRIBUTE_PRINTER_ADD("DO-COMPLETE-FIRST", PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST); 153 | ATTRIBUTE_PRINTER_ADD("ENABLE-DEVQ", PRINTER_ATTRIBUTE_ENABLE_DEVQ); 154 | ATTRIBUTE_PRINTER_ADD("HIDDEN", PRINTER_ATTRIBUTE_HIDDEN); 155 | ATTRIBUTE_PRINTER_ADD("KEEPPRINTEDJOBS", PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS); 156 | ATTRIBUTE_PRINTER_ADD("LOCAL", PRINTER_ATTRIBUTE_LOCAL); 157 | ATTRIBUTE_PRINTER_ADD("NETWORK", PRINTER_ATTRIBUTE_NETWORK); 158 | ATTRIBUTE_PRINTER_ADD("PUBLISHED", PRINTER_ATTRIBUTE_PUBLISHED); 159 | ATTRIBUTE_PRINTER_ADD("QUEUED", PRINTER_ATTRIBUTE_QUEUED); 160 | ATTRIBUTE_PRINTER_ADD("RAW-ONLY", PRINTER_ATTRIBUTE_RAW_ONLY); 161 | ATTRIBUTE_PRINTER_ADD("SHARED", PRINTER_ATTRIBUTE_SHARED); 162 | ATTRIBUTE_PRINTER_ADD("OFFLINE", PRINTER_ATTRIBUTE_WORK_OFFLINE); 163 | // XP 164 | #ifdef PRINTER_ATTRIBUTE_FAX 165 | ATTRIBUTE_PRINTER_ADD("FAX", PRINTER_ATTRIBUTE_FAX); 166 | #endif 167 | // vista 168 | #ifdef PRINTER_ATTRIBUTE_FRIENDLY_NAME 169 | ATTRIBUTE_PRINTER_ADD("FRIENDLY-NAME", PRINTER_ATTRIBUTE_FRIENDLY_NAME); 170 | ATTRIBUTE_PRINTER_ADD("MACHINE", PRINTER_ATTRIBUTE_MACHINE); 171 | ATTRIBUTE_PRINTER_ADD("PUSHED-USER", PRINTER_ATTRIBUTE_PUSHED_USER); 172 | ATTRIBUTE_PRINTER_ADD("PUSHED-MACHINE", PRINTER_ATTRIBUTE_PUSHED_MACHINE); 173 | #endif 174 | // server 2003 175 | #ifdef PRINTER_ATTRIBUTE_TS 176 | ATTRIBUTE_PRINTER_ADD("TS", PRINTER_ATTRIBUTE_TS); 177 | #endif 178 | #undef ATTRIBUTE_PRINTER_ADD 179 | return result; 180 | } 181 | 182 | const StatusMapType& getJobCommandMap() 183 | { 184 | static StatusMapType result; 185 | if(!result.empty()) 186 | { 187 | return result; 188 | } 189 | // add only first time 190 | #define COMMAND_JOB_ADD(value, type) result.insert(std::make_pair(value, type)) 191 | COMMAND_JOB_ADD("CANCEL", JOB_CONTROL_CANCEL); 192 | COMMAND_JOB_ADD("PAUSE", JOB_CONTROL_PAUSE); 193 | COMMAND_JOB_ADD("RESTART", JOB_CONTROL_RESTART); 194 | COMMAND_JOB_ADD("RESUME", JOB_CONTROL_RESUME); 195 | COMMAND_JOB_ADD("DELETE", JOB_CONTROL_DELETE); 196 | COMMAND_JOB_ADD("SENT-TO-PRINTER", JOB_CONTROL_SENT_TO_PRINTER); 197 | COMMAND_JOB_ADD("LAST-PAGE-EJECTED", JOB_CONTROL_LAST_PAGE_EJECTED); 198 | #ifdef JOB_CONTROL_RETAIN 199 | COMMAND_JOB_ADD("RETAIN", JOB_CONTROL_RETAIN); 200 | #endif 201 | #ifdef JOB_CONTROL_RELEASE 202 | COMMAND_JOB_ADD("RELEASE", JOB_CONTROL_RELEASE); 203 | #endif 204 | #undef COMMAND_JOB_ADD 205 | return result; 206 | } 207 | 208 | void parseJobObject(JOB_INFO_2W *job, v8::Handle result_printer_job) 209 | { 210 | MY_NODE_MODULE_ISOLATE_DECL 211 | //Common fields 212 | //DWORD JobId; 213 | result_printer_job->Set(V8_STRING_NEW_UTF8("id"), V8_VALUE_NEW(Number, job->JobId)); 214 | #define ADD_V8_STRING_PROPERTY(name, key) if((job->##key != NULL) && (*job->##key != L'\0')) \ 215 | { \ 216 | result_printer_job->Set(V8_STRING_NEW_UTF8(#name), V8_STRING_NEW_2BYTES((uint16_t*)job->##key)); \ 217 | } 218 | //LPTSTR pPrinterName; 219 | ADD_V8_STRING_PROPERTY(name, pPrinterName) 220 | //LPTSTR pPrinterName; 221 | ADD_V8_STRING_PROPERTY(printerName, pPrinterName); 222 | //LPTSTR pUserName; 223 | ADD_V8_STRING_PROPERTY(user, pUserName); 224 | //LPTSTR pDatatype; 225 | ADD_V8_STRING_PROPERTY(format, pDatatype); 226 | //DWORD Priority; 227 | result_printer_job->Set(V8_STRING_NEW_UTF8("priority"), V8_VALUE_NEW(Number, job->Priority)); 228 | //DWORD Size; 229 | result_printer_job->Set(V8_STRING_NEW_UTF8("size"), V8_VALUE_NEW(Number, job->Size)); 230 | //DWORD Status; 231 | v8::Local result_printer_job_status = V8_VALUE_NEW_DEFAULT_V_0_11_10(Array); 232 | int i_status = 0; 233 | for(StatusMapType::const_iterator itStatus = getJobStatusMap().begin(); itStatus != getJobStatusMap().end(); ++itStatus) 234 | { 235 | if(job->Status & itStatus->second) 236 | { 237 | result_printer_job_status->Set(i_status++, V8_STRING_NEW_UTF8(itStatus->first.c_str())); 238 | } 239 | } 240 | //LPTSTR pStatus; 241 | if((job->pStatus != NULL) && (*job->pStatus != L'\0')) 242 | { 243 | result_printer_job_status->Set(i_status++, V8_STRING_NEW_2BYTES((uint16_t*)job->pStatus)); 244 | } 245 | result_printer_job->Set(V8_STRING_NEW_UTF8("status"), result_printer_job_status); 246 | 247 | // Specific fields 248 | //LPTSTR pMachineName; 249 | ADD_V8_STRING_PROPERTY(machineName, pMachineName); 250 | //LPTSTR pDocument; 251 | ADD_V8_STRING_PROPERTY(document, pDocument); 252 | //LPTSTR pNotifyName; 253 | ADD_V8_STRING_PROPERTY(notifyName, pNotifyName); 254 | //LPTSTR pPrintProcessor; 255 | ADD_V8_STRING_PROPERTY(printProcessor, pPrintProcessor); 256 | //LPTSTR pParameters; 257 | ADD_V8_STRING_PROPERTY(parameters, pParameters); 258 | //LPTSTR pDriverName; 259 | ADD_V8_STRING_PROPERTY(driverName, pDriverName); 260 | #undef ADD_V8_STRING_PROPERTY 261 | //LPDEVMODE pDevMode; 262 | //PSECURITY_DESCRIPTOR pSecurityDescriptor; 263 | //DWORD Position; 264 | result_printer_job->Set(V8_STRING_NEW_UTF8("position"), V8_VALUE_NEW(Number, job->Position)); 265 | //DWORD StartTime; 266 | result_printer_job->Set(V8_STRING_NEW_UTF8("startTime"), V8_VALUE_NEW(Number, job->StartTime)); 267 | //DWORD UntilTime; 268 | result_printer_job->Set(V8_STRING_NEW_UTF8("untilTime"), V8_VALUE_NEW(Number, job->UntilTime)); 269 | //DWORD TotalPages; 270 | result_printer_job->Set(V8_STRING_NEW_UTF8("totalPages"), V8_VALUE_NEW(Number, job->TotalPages)); 271 | //SYSTEMTIME Submitted; 272 | //DWORD Time; 273 | result_printer_job->Set(V8_STRING_NEW_UTF8("time"), V8_VALUE_NEW(Number, job->Time)); 274 | //DWORD PagesPrinted; 275 | result_printer_job->Set(V8_STRING_NEW_UTF8("pagesPrinted"), V8_VALUE_NEW(Number, job->PagesPrinted)); 276 | } 277 | 278 | /** 279 | * Returns last error code and message string 280 | */ 281 | std::string getLastErrorCodeAndMessage() { 282 | std::ostringstream s; 283 | DWORD erroCode = GetLastError(); 284 | s << "code: " << erroCode; 285 | DWORD retSize; 286 | LPTSTR pTemp = NULL; 287 | retSize = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER| 288 | FORMAT_MESSAGE_FROM_SYSTEM| 289 | FORMAT_MESSAGE_ARGUMENT_ARRAY, 290 | NULL, 291 | erroCode, 292 | LANG_NEUTRAL, 293 | (LPTSTR)&pTemp, 294 | 0, 295 | NULL ); 296 | if (retSize && pTemp != NULL) { 297 | //pTemp[strlen(pTemp)-2]='\0'; //remove cr and newline character 298 | //TODO: check if it is needed to convert c string to std::string 299 | std::string stringMessage(pTemp); 300 | s << ", message: " << stringMessage; 301 | LocalFree((HLOCAL)pTemp); 302 | } 303 | 304 | return s.str(); 305 | } 306 | 307 | std::string retrieveAndParseJobs(const LPWSTR iPrinterName, 308 | const DWORD& iTotalJobs, 309 | v8::Handle result_printer_jobs, 310 | PrinterHandle& iPrinterHandle) 311 | { 312 | MY_NODE_MODULE_ISOLATE_DECL 313 | DWORD bytes_needed = 0, totalJobs = 0; 314 | BOOL bError = EnumJobsW(*iPrinterHandle, 0, iTotalJobs, 2, NULL, bytes_needed, &bytes_needed, &totalJobs); 315 | MemValue jobs(bytes_needed); 316 | if(!jobs) 317 | { 318 | std::string error_str("Error on allocating memory for jobs: "); 319 | error_str += getLastErrorCodeAndMessage(); 320 | return error_str; 321 | } 322 | DWORD dummy_bytes = 0; 323 | bError = EnumJobsW(*iPrinterHandle, 0, iTotalJobs, 2, (LPBYTE)jobs.get(), bytes_needed, &dummy_bytes, &totalJobs); 324 | if(!bError) 325 | { 326 | std::string error_str("Error on EnumJobsW: "); 327 | error_str += getLastErrorCodeAndMessage(); 328 | return error_str; 329 | } 330 | JOB_INFO_2W *job = jobs.get(); 331 | for(DWORD i = 0; i < totalJobs; ++i, ++job) 332 | { 333 | v8::Local result_printer_job = V8_VALUE_NEW_DEFAULT_V_0_11_10(Object); 334 | parseJobObject(job, result_printer_job); 335 | result_printer_jobs->Set(i, result_printer_job); 336 | } 337 | return std::string(""); 338 | } 339 | 340 | std::string parsePrinterInfo(const PRINTER_INFO_2W *printer, v8::Handle result_printer, PrinterHandle& iPrinterHandle) 341 | { 342 | MY_NODE_MODULE_ISOLATE_DECL 343 | #define ADD_V8_STRING_PROPERTY(name, key) if((printer->##key != NULL) && (*printer->##key != L'\0')) \ 344 | { \ 345 | result_printer->Set(V8_STRING_NEW_UTF8(#name), V8_STRING_NEW_2BYTES((uint16_t*)printer->##key)); \ 346 | } 347 | //LPTSTR pPrinterName; 348 | ADD_V8_STRING_PROPERTY(name, pPrinterName) 349 | //LPTSTR pServerName; 350 | ADD_V8_STRING_PROPERTY(serverName, pServerName) 351 | //LPTSTR pShareName; 352 | ADD_V8_STRING_PROPERTY(shareName, pShareName) 353 | //LPTSTR pPortName; 354 | ADD_V8_STRING_PROPERTY(portName, pPortName) 355 | //LPTSTR pDriverName; 356 | ADD_V8_STRING_PROPERTY(driverName, pDriverName) 357 | //LPTSTR pComment; 358 | ADD_V8_STRING_PROPERTY(comment, pComment) 359 | //LPTSTR pLocation; 360 | ADD_V8_STRING_PROPERTY(location, pLocation) 361 | //LPTSTR pSepFile; 362 | ADD_V8_STRING_PROPERTY(sepFile, pSepFile) 363 | //LPTSTR pPrintProcessor; 364 | ADD_V8_STRING_PROPERTY(printProcessor, pPrintProcessor) 365 | //LPTSTR pDatatype; 366 | ADD_V8_STRING_PROPERTY(datatype, pDatatype) 367 | //LPTSTR pParameters; 368 | ADD_V8_STRING_PROPERTY(parameters, pParameters) 369 | #undef ADD_V8_STRING_PROPERTY 370 | //DWORD Status; 371 | // statuses from: 372 | // http://msdn.microsoft.com/en-gb/library/windows/desktop/dd162845(v=vs.85).aspx 373 | v8::Local result_printer_status = V8_VALUE_NEW_DEFAULT_V_0_11_10(Array); 374 | int i_status = 0; 375 | for(StatusMapType::const_iterator itStatus = getStatusMap().begin(); itStatus != getStatusMap().end(); ++itStatus) 376 | { 377 | if(printer->Status & itStatus->second) 378 | { 379 | result_printer_status->Set(i_status, V8_STRING_NEW_UTF8(itStatus->first.c_str())); 380 | ++i_status; 381 | } 382 | } 383 | result_printer->Set(V8_STRING_NEW_UTF8("status"), result_printer_status); 384 | result_printer->Set(V8_STRING_NEW_UTF8("statusNumber"), V8_VALUE_NEW(Number, printer->Status)); 385 | //DWORD Attributes; 386 | v8::Local result_printer_attributes = V8_VALUE_NEW_DEFAULT_V_0_11_10(Array); 387 | int i_attribute = 0; 388 | for(StatusMapType::const_iterator itAttribute = getAttributeMap().begin(); itAttribute != getAttributeMap().end(); ++itAttribute) 389 | { 390 | if(printer->Attributes & itAttribute->second) 391 | { 392 | result_printer_attributes->Set(i_attribute, V8_STRING_NEW_UTF8(itAttribute->first.c_str())); 393 | ++i_attribute; 394 | } 395 | } 396 | result_printer->Set(V8_STRING_NEW_UTF8("attributes"), result_printer_attributes); 397 | //DWORD Priority; 398 | result_printer->Set(V8_STRING_NEW_UTF8("priority"), V8_VALUE_NEW(Number, printer->Priority)); 399 | //DWORD DefaultPriority; 400 | result_printer->Set(V8_STRING_NEW_UTF8("defaultPriority"), V8_VALUE_NEW(Number, printer->DefaultPriority)); 401 | //DWORD cJobs; 402 | //result_printer->Set(V8_STRING_NEW_UTF8("jobs"), V8_VALUE_NEW(Number, printer->cJobs)); 403 | //DWORD AveragePPM; 404 | result_printer->Set(V8_STRING_NEW_UTF8("averagePPM"), V8_VALUE_NEW(Number, printer->AveragePPM)); 405 | 406 | //DWORD StartTime; 407 | if(printer->StartTime > 0) 408 | { 409 | result_printer->Set(V8_STRING_NEW_UTF8("startTime"), V8_VALUE_NEW(Number, printer->StartTime)); 410 | } 411 | //DWORD UntilTime; 412 | if(printer->UntilTime > 0) 413 | { 414 | result_printer->Set(V8_STRING_NEW_UTF8("untilTime"), V8_VALUE_NEW(Number, printer->UntilTime)); 415 | } 416 | 417 | //TODO: to finish to extract all data 418 | //LPDEVMODE pDevMode; 419 | //PSECURITY_DESCRIPTOR pSecurityDescriptor; 420 | 421 | if(printer->cJobs > 0) 422 | { 423 | v8::Local result_printer_jobs = V8_VALUE_NEW_V_0_11_10(Array, printer->cJobs); 424 | // get jobs 425 | std::string error_str = retrieveAndParseJobs(printer->pPrinterName, printer->cJobs, result_printer_jobs, iPrinterHandle); 426 | if(!error_str.empty()) 427 | { 428 | return error_str; 429 | } 430 | result_printer->Set(V8_STRING_NEW_UTF8("jobs"), result_printer_jobs); 431 | } 432 | return ""; 433 | } 434 | } 435 | 436 | MY_NODE_MODULE_CALLBACK(getPrinters) 437 | { 438 | MY_NODE_MODULE_HANDLESCOPE; 439 | DWORD printers_size = 0; 440 | DWORD printers_size_bytes = 0, dummyBytes = 0; 441 | DWORD Level = 2; 442 | DWORD flags = PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS;// https://msdn.microsoft.com/en-us/library/cc244669.aspx 443 | // First try to retrieve the number of printers 444 | BOOL bError = EnumPrintersW(flags, NULL, 2, NULL, 0, &printers_size_bytes, &printers_size); 445 | // allocate the required memmory 446 | MemValue printers(printers_size_bytes); 447 | if(!printers) 448 | { 449 | RETURN_EXCEPTION_STR("Error on allocating memory for printers"); 450 | } 451 | 452 | bError = EnumPrintersW(flags, NULL, 2, (LPBYTE)(printers.get()), printers_size_bytes, &dummyBytes, &printers_size); 453 | if(!bError) 454 | { 455 | std::string error_str("Error on EnumPrinters: "); 456 | error_str += getLastErrorCodeAndMessage(); 457 | RETURN_EXCEPTION_STR(error_str.c_str()); 458 | } 459 | v8::Local result = V8_VALUE_NEW_V_0_11_10(Array, printers_size); 460 | // http://msdn.microsoft.com/en-gb/library/windows/desktop/dd162845(v=vs.85).aspx 461 | PRINTER_INFO_2W *printer = printers.get(); 462 | DWORD i = 0; 463 | for(; i < printers_size; ++i, ++printer) 464 | { 465 | v8::Local result_printer = V8_VALUE_NEW_DEFAULT_V_0_11_10(Object); 466 | PrinterHandle printerHandle((LPWSTR)(printer->pPrinterName)); 467 | std::string error_str = parsePrinterInfo(printer, result_printer, printerHandle); 468 | if(!error_str.empty()) 469 | { 470 | RETURN_EXCEPTION_STR(error_str.c_str()); 471 | } 472 | result->Set(i, result_printer); 473 | } 474 | MY_NODE_MODULE_RETURN_VALUE(result); 475 | } 476 | 477 | MY_NODE_MODULE_CALLBACK(getDefaultPrinterName) 478 | { 479 | MY_NODE_MODULE_HANDLESCOPE; 480 | // size in chars of the printer name: https://msdn.microsoft.com/en-us/library/windows/desktop/dd144876(v=vs.85).aspx 481 | DWORD cSize = 0; 482 | GetDefaultPrinterW(NULL, &cSize); 483 | 484 | if(cSize == 0) { 485 | MY_NODE_MODULE_RETURN_VALUE(V8_STRING_NEW_UTF8("")); 486 | } 487 | 488 | MemValue bPrinterName(cSize*sizeof(uint16_t)); 489 | BOOL res = GetDefaultPrinterW((LPWSTR)(bPrinterName.get()), &cSize); 490 | 491 | if(!res) { 492 | MY_NODE_MODULE_RETURN_VALUE(V8_STRING_NEW_UTF8("")); 493 | } 494 | 495 | MY_NODE_MODULE_RETURN_VALUE(V8_STRING_NEW_2BYTES((uint16_t*)bPrinterName.get())); 496 | } 497 | 498 | MY_NODE_MODULE_CALLBACK(getPrinter) 499 | { 500 | MY_NODE_MODULE_HANDLESCOPE; 501 | REQUIRE_ARGUMENTS(iArgs, 1); 502 | REQUIRE_ARGUMENT_STRINGW(iArgs, 0, printername); 503 | 504 | // Open a handle to the printer. 505 | PrinterHandle printerHandle((LPWSTR)(*printername)); 506 | if(!printerHandle) 507 | { 508 | std::string error_str("error on PrinterHandle: "); 509 | error_str += getLastErrorCodeAndMessage(); 510 | RETURN_EXCEPTION_STR(error_str.c_str()); 511 | } 512 | DWORD printers_size_bytes = 0, dummyBytes = 0; 513 | GetPrinterW(*printerHandle, 2, NULL, printers_size_bytes, &printers_size_bytes); 514 | MemValue printer(printers_size_bytes); 515 | if(!printer) 516 | { 517 | RETURN_EXCEPTION_STR("Error on allocating memory for printers"); 518 | } 519 | BOOL bOK = GetPrinterW(*printerHandle, 2, (LPBYTE)(printer.get()), printers_size_bytes, &printers_size_bytes); 520 | if(!bOK) 521 | { 522 | std::string error_str("Error on GetPrinter: "); 523 | error_str += getLastErrorCodeAndMessage(); 524 | RETURN_EXCEPTION_STR(error_str.c_str()); 525 | } 526 | v8::Local result_printer = V8_VALUE_NEW_DEFAULT_V_0_11_10(Object); 527 | std::string error_str = parsePrinterInfo(printer.get(), result_printer, printerHandle); 528 | if(!error_str.empty()) 529 | { 530 | RETURN_EXCEPTION_STR(error_str.c_str()); 531 | } 532 | 533 | MY_NODE_MODULE_RETURN_VALUE(result_printer); 534 | } 535 | 536 | MY_NODE_MODULE_CALLBACK(getPrinterDriverOptions) 537 | { 538 | MY_NODE_MODULE_HANDLESCOPE; 539 | RETURN_EXCEPTION_STR("not supported on windows"); 540 | } 541 | 542 | MY_NODE_MODULE_CALLBACK(getJob) 543 | { 544 | MY_NODE_MODULE_HANDLESCOPE; 545 | REQUIRE_ARGUMENTS(iArgs, 2); 546 | REQUIRE_ARGUMENT_STRINGW(iArgs, 0, printername); 547 | REQUIRE_ARGUMENT_INTEGER(iArgs, 1, jobId); 548 | if(jobId < 0) 549 | { 550 | RETURN_EXCEPTION_STR("Wrong job number"); 551 | } 552 | // Open a handle to the printer. 553 | PrinterHandle printerHandle((LPWSTR)(*printername)); 554 | if(!printerHandle) 555 | { 556 | std::string error_str("error on PrinterHandle: "); 557 | error_str += getLastErrorCodeAndMessage(); 558 | RETURN_EXCEPTION_STR(error_str.c_str()); 559 | } 560 | DWORD size_bytes = 0, dummyBytes = 0; 561 | GetJobW(*printerHandle, static_cast(jobId), 2, NULL, size_bytes, &size_bytes); 562 | MemValue job(size_bytes); 563 | if(!job) 564 | { 565 | RETURN_EXCEPTION_STR("Error on allocating memory for printers"); 566 | } 567 | BOOL bOK = GetJobW(*printerHandle, static_cast(jobId), 2, (LPBYTE)job.get(), size_bytes, &dummyBytes); 568 | if(!bOK) 569 | { 570 | std::string error_str("Error on GetJob. Wrong job id or it was deleted: "); 571 | error_str += getLastErrorCodeAndMessage(); 572 | RETURN_EXCEPTION_STR(error_str.c_str()); 573 | } 574 | v8::Local result_printer_job = V8_VALUE_NEW_DEFAULT_V_0_11_10(Object); 575 | parseJobObject(job.get(), result_printer_job); 576 | MY_NODE_MODULE_RETURN_VALUE(result_printer_job); 577 | } 578 | 579 | MY_NODE_MODULE_CALLBACK(setJob) 580 | { 581 | MY_NODE_MODULE_HANDLESCOPE; 582 | REQUIRE_ARGUMENTS(iArgs, 3); 583 | REQUIRE_ARGUMENT_STRINGW(iArgs, 0, printername); 584 | REQUIRE_ARGUMENT_INTEGER(iArgs, 1, jobId); 585 | REQUIRE_ARGUMENT_STRING(iArgs, 2, jobCommandV8); 586 | if(jobId < 0) 587 | { 588 | RETURN_EXCEPTION_STR("Wrong job number"); 589 | } 590 | std::string jobCommandStr(*jobCommandV8); 591 | StatusMapType::const_iterator itJobCommand = getJobCommandMap().find(jobCommandStr); 592 | if(itJobCommand == getJobCommandMap().end()) 593 | { 594 | RETURN_EXCEPTION_STR("wrong job command. use getSupportedJobCommands to see the possible commands"); 595 | } 596 | DWORD jobCommand = itJobCommand->second; 597 | // Open a handle to the printer. 598 | PrinterHandle printerHandle((LPWSTR)(*printername)); 599 | if(!printerHandle) 600 | { 601 | std::string error_str("error on PrinterHandle: "); 602 | error_str += getLastErrorCodeAndMessage(); 603 | RETURN_EXCEPTION_STR(error_str.c_str()); 604 | } 605 | // TODO: add the possibility to set job properties 606 | // http://msdn.microsoft.com/en-us/library/windows/desktop/dd162978(v=vs.85).aspx 607 | BOOL ok = SetJobW(*printerHandle, (DWORD)jobId, 0, NULL, jobCommand); 608 | MY_NODE_MODULE_RETURN_VALUE(V8_VALUE_NEW_V_0_11_10(Boolean, ok == TRUE)); 609 | } 610 | 611 | MY_NODE_MODULE_CALLBACK(getSupportedJobCommands) 612 | { 613 | MY_NODE_MODULE_HANDLESCOPE; 614 | v8::Local result = V8_VALUE_NEW_DEFAULT_V_0_11_10(Array); 615 | int i = 0; 616 | for(StatusMapType::const_iterator itJob = getJobCommandMap().begin(); itJob != getJobCommandMap().end(); ++itJob) 617 | { 618 | result->Set(i++, V8_STRING_NEW_UTF8(itJob->first.c_str())); 619 | } 620 | MY_NODE_MODULE_RETURN_VALUE(result); 621 | } 622 | 623 | MY_NODE_MODULE_CALLBACK(getSupportedPrintFormats) 624 | { 625 | MY_NODE_MODULE_HANDLESCOPE; 626 | v8::Local result = V8_VALUE_NEW_DEFAULT_V_0_11_10(Array); 627 | int format_i = 0; 628 | 629 | LPTSTR name = NULL; 630 | DWORD numBytes = 0, processorsNum = 0; 631 | 632 | // Check the amount of bytes required 633 | LPWSTR nullVal = NULL; 634 | EnumPrintProcessorsW(nullVal, nullVal, 1, (LPBYTE)(NULL), numBytes, &numBytes, &processorsNum); 635 | MemValue<_PRINTPROCESSOR_INFO_1W> processors(numBytes); 636 | // Retrieve processors 637 | BOOL isOK = EnumPrintProcessorsW(nullVal, nullVal, 1, (LPBYTE)(processors.get()), numBytes, &numBytes, &processorsNum); 638 | 639 | if(!isOK) { 640 | std::string error_str("error on EnumPrintProcessorsW: "); 641 | error_str += getLastErrorCodeAndMessage(); 642 | RETURN_EXCEPTION_STR(error_str.c_str()); 643 | } 644 | 645 | _PRINTPROCESSOR_INFO_1W *pProcessor = processors.get(); 646 | 647 | for(DWORD processor_i = 0; processor_i < processorsNum; ++processor_i, ++pProcessor) { 648 | numBytes = 0; 649 | DWORD dataTypesNum = 0; 650 | EnumPrintProcessorDatatypesW(nullVal, pProcessor->pName, 1, (LPBYTE)(NULL), numBytes, &numBytes, &dataTypesNum); 651 | MemValue<_DATATYPES_INFO_1W> dataTypes(numBytes); 652 | isOK = EnumPrintProcessorDatatypesW(nullVal, pProcessor->pName, 1, (LPBYTE)(dataTypes.get()), numBytes, &numBytes, &dataTypesNum); 653 | 654 | if(!isOK) { 655 | std::string error_str("error on EnumPrintProcessorDatatypesW: "); 656 | error_str += getLastErrorCodeAndMessage(); 657 | RETURN_EXCEPTION_STR(error_str.c_str()); 658 | } 659 | 660 | _DATATYPES_INFO_1W *pDataType = dataTypes.get(); 661 | for(DWORD j = 0; j < dataTypesNum; ++j, ++pDataType) { 662 | result->Set(format_i++, V8_STRING_NEW_2BYTES((uint16_t*)(pDataType->pName))); 663 | } 664 | } 665 | 666 | MY_NODE_MODULE_RETURN_VALUE(result); 667 | } 668 | 669 | MY_NODE_MODULE_CALLBACK(PrintDirect) 670 | { 671 | MY_NODE_MODULE_HANDLESCOPE; 672 | //TODO: to move in an unique place win and posix input parameters processing 673 | REQUIRE_ARGUMENTS(iArgs, 5); 674 | 675 | // can be string or buffer 676 | if(iArgs.Length()<=0) 677 | { 678 | RETURN_EXCEPTION_STR("Argument 0 missing"); 679 | } 680 | 681 | std::string data; 682 | v8::Handle arg0(iArgs[0]); 683 | if (!getStringOrBufferFromV8Value(arg0, data)) 684 | { 685 | RETURN_EXCEPTION_STR("Argument 0 must be a string or Buffer"); 686 | } 687 | 688 | REQUIRE_ARGUMENT_STRINGW(iArgs, 1, printername); 689 | REQUIRE_ARGUMENT_STRINGW(iArgs, 2, docname); 690 | REQUIRE_ARGUMENT_STRINGW(iArgs, 3, type); 691 | 692 | BOOL bStatus = true; 693 | // Open a handle to the printer. 694 | PrinterHandle printerHandle((LPWSTR)(*printername)); 695 | DOC_INFO_1W DocInfo; 696 | DWORD dwJob = 0L; 697 | DWORD dwBytesWritten = 0L; 698 | 699 | if (!printerHandle) 700 | { 701 | std::string error_str("error on PrinterHandle: "); 702 | error_str += getLastErrorCodeAndMessage(); 703 | RETURN_EXCEPTION_STR(error_str.c_str()); 704 | } 705 | 706 | // Fill in the structure with info about this "document." 707 | DocInfo.pDocName = (LPWSTR)(*docname); 708 | DocInfo.pOutputFile = NULL; 709 | DocInfo.pDatatype = (LPWSTR)(*type); 710 | 711 | // Inform the spooler the document is beginning. 712 | dwJob = StartDocPrinterW(*printerHandle, 1, (LPBYTE)&DocInfo ); 713 | if (dwJob > 0) { 714 | // Start a page. 715 | bStatus = StartPagePrinter(*printerHandle); 716 | if (bStatus) { 717 | // Send the data to the printer. 718 | //TODO: check with sizeof(LPTSTR) is the same as sizeof(char) 719 | bStatus = WritePrinter( *printerHandle, (LPVOID)(data.c_str()), (DWORD)data.size(), &dwBytesWritten); 720 | EndPagePrinter(*printerHandle); 721 | }else{ 722 | std::string error_str("StartPagePrinter error: "); 723 | error_str += getLastErrorCodeAndMessage(); 724 | RETURN_EXCEPTION_STR(error_str.c_str()); 725 | } 726 | // Inform the spooler that the document is ending. 727 | EndDocPrinter(*printerHandle); 728 | }else{ 729 | std::string error_str("StartDocPrinterW error: "); 730 | error_str += getLastErrorCodeAndMessage(); 731 | RETURN_EXCEPTION_STR(error_str.c_str()); 732 | } 733 | // Check to see if correct number of bytes were written. 734 | if (dwBytesWritten != data.size()) { 735 | RETURN_EXCEPTION_STR("not sent all bytes"); 736 | } 737 | MY_NODE_MODULE_RETURN_VALUE(V8_VALUE_NEW(Number, dwJob)); 738 | } 739 | 740 | MY_NODE_MODULE_CALLBACK(PrintFile) 741 | { 742 | MY_NODE_MODULE_HANDLESCOPE; 743 | RETURN_EXCEPTION_STR("Not yet implemented on Windows"); 744 | } 745 | -------------------------------------------------------------------------------- /node_modules/printer/tools/getSourceFiles.py: -------------------------------------------------------------------------------- 1 | # simple python command to list files like ls -1 2 | import os, sys 3 | 4 | if len(sys.argv) < 3: 5 | sys.stderr.write('use: '+sys.argv[0]+' . e.g.:'+sys.argv[0]+' src cc\n') 6 | sys.exit(1) 7 | folder = sys.argv[1] 8 | file_ext = '.'+sys.argv[2] 9 | 10 | for file in os.listdir(folder): 11 | if (file.endswith(file_ext)): 12 | print(folder+'/'+file) 13 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "all-embracing", 3 | "version": "0.0.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "7zip-bin": { 8 | "version": "2.4.1", 9 | "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-2.4.1.tgz", 10 | "integrity": "sha512-QU3oR1dLLVrYGRkb7LU17jMCpIkWtXXW7q71ECXWXkR9vOv37VjykqpvFgs29HgSCNLZHnNKJzdG6RwAW0LwIA==", 11 | "dev": true, 12 | "requires": { 13 | "7zip-bin-linux": "~1.3.1", 14 | "7zip-bin-mac": "~1.0.1", 15 | "7zip-bin-win": "~2.1.1" 16 | } 17 | }, 18 | "7zip-bin-linux": { 19 | "version": "1.3.1", 20 | "resolved": "https://registry.npmjs.org/7zip-bin-linux/-/7zip-bin-linux-1.3.1.tgz", 21 | "integrity": "sha512-Wv1uEEeHbTiS1+ycpwUxYNuIcyohU6Y6vEqY3NquBkeqy0YhVdsNUGsj0XKSRciHR6LoJSEUuqYUexmws3zH7Q==", 22 | "dev": true, 23 | "optional": true 24 | }, 25 | "7zip-bin-mac": { 26 | "version": "1.0.1", 27 | "resolved": "https://registry.npmjs.org/7zip-bin-mac/-/7zip-bin-mac-1.0.1.tgz", 28 | "integrity": "sha1-Pmh3i78JJq3GgVlCcHRQXUdVXAI=", 29 | "dev": true, 30 | "optional": true 31 | }, 32 | "7zip-bin-win": { 33 | "version": "2.1.1", 34 | "resolved": "https://registry.npmjs.org/7zip-bin-win/-/7zip-bin-win-2.1.1.tgz", 35 | "integrity": "sha512-6VGEW7PXGroTsoI2QW3b0ea95HJmbVBHvfANKLLMzSzFA1zKqVX5ybNuhmeGpf6vA0x8FJTt6twpprDANsY5WQ==", 36 | "dev": true, 37 | "optional": true 38 | }, 39 | "ajv": { 40 | "version": "6.6.1", 41 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz", 42 | "integrity": "sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==", 43 | "dev": true, 44 | "requires": { 45 | "fast-deep-equal": "^2.0.1", 46 | "fast-json-stable-stringify": "^2.0.0", 47 | "json-schema-traverse": "^0.4.1", 48 | "uri-js": "^4.2.2" 49 | } 50 | }, 51 | "ansi-regex": { 52 | "version": "2.1.1", 53 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 54 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 55 | }, 56 | "ansi-styles": { 57 | "version": "2.2.1", 58 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 59 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" 60 | }, 61 | "array-differ": { 62 | "version": "0.1.0", 63 | "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-0.1.0.tgz", 64 | "integrity": "sha1-EuLJtwa+1HyLSDtX5IdHP7CGHzo=" 65 | }, 66 | "array-union": { 67 | "version": "1.0.2", 68 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", 69 | "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", 70 | "dev": true, 71 | "requires": { 72 | "array-uniq": "^1.0.1" 73 | } 74 | }, 75 | "array-uniq": { 76 | "version": "1.0.3", 77 | "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", 78 | "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", 79 | "dev": true 80 | }, 81 | "asn1": { 82 | "version": "0.2.4", 83 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 84 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 85 | "dev": true, 86 | "requires": { 87 | "safer-buffer": "~2.1.0" 88 | } 89 | }, 90 | "assert-plus": { 91 | "version": "1.0.0", 92 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 93 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 94 | "dev": true 95 | }, 96 | "async": { 97 | "version": "0.9.2", 98 | "resolved": "http://registry.npmjs.org/async/-/async-0.9.2.tgz", 99 | "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" 100 | }, 101 | "asynckit": { 102 | "version": "0.4.0", 103 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 104 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", 105 | "dev": true 106 | }, 107 | "aws-sign2": { 108 | "version": "0.7.0", 109 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 110 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", 111 | "dev": true 112 | }, 113 | "aws4": { 114 | "version": "1.8.0", 115 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", 116 | "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", 117 | "dev": true 118 | }, 119 | "balanced-match": { 120 | "version": "1.0.0", 121 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 122 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 123 | }, 124 | "base64-js": { 125 | "version": "1.2.0", 126 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.0.tgz", 127 | "integrity": "sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE=", 128 | "dev": true 129 | }, 130 | "bcrypt-pbkdf": { 131 | "version": "1.0.2", 132 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 133 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 134 | "dev": true, 135 | "requires": { 136 | "tweetnacl": "^0.14.3" 137 | } 138 | }, 139 | "bl": { 140 | "version": "1.0.3", 141 | "resolved": "http://registry.npmjs.org/bl/-/bl-1.0.3.tgz", 142 | "integrity": "sha1-/FQhoo/UImA2w7OJGmaiW8ZNIm4=", 143 | "requires": { 144 | "readable-stream": "~2.0.5" 145 | } 146 | }, 147 | "block-stream": { 148 | "version": "0.0.9", 149 | "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", 150 | "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", 151 | "requires": { 152 | "inherits": "~2.0.0" 153 | } 154 | }, 155 | "bluebird": { 156 | "version": "3.5.3", 157 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", 158 | "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", 159 | "dev": true 160 | }, 161 | "boom": { 162 | "version": "2.10.1", 163 | "resolved": "http://registry.npmjs.org/boom/-/boom-2.10.1.tgz", 164 | "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", 165 | "requires": { 166 | "hoek": "2.x.x" 167 | } 168 | }, 169 | "brace-expansion": { 170 | "version": "1.1.11", 171 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 172 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 173 | "requires": { 174 | "balanced-match": "^1.0.0", 175 | "concat-map": "0.0.1" 176 | } 177 | }, 178 | "buffer-equal": { 179 | "version": "1.0.0", 180 | "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", 181 | "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", 182 | "dev": true 183 | }, 184 | "builtin-modules": { 185 | "version": "1.1.1", 186 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", 187 | "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", 188 | "dev": true 189 | }, 190 | "camelcase": { 191 | "version": "3.0.0", 192 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", 193 | "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", 194 | "dev": true 195 | }, 196 | "caseless": { 197 | "version": "0.12.0", 198 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 199 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", 200 | "dev": true 201 | }, 202 | "chalk": { 203 | "version": "1.1.3", 204 | "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 205 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 206 | "requires": { 207 | "ansi-styles": "^2.2.1", 208 | "escape-string-regexp": "^1.0.2", 209 | "has-ansi": "^2.0.0", 210 | "strip-ansi": "^3.0.0", 211 | "supports-color": "^2.0.0" 212 | } 213 | }, 214 | "cliui": { 215 | "version": "3.2.0", 216 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", 217 | "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", 218 | "dev": true, 219 | "requires": { 220 | "string-width": "^1.0.1", 221 | "strip-ansi": "^3.0.1", 222 | "wrap-ansi": "^2.0.0" 223 | } 224 | }, 225 | "code-point-at": { 226 | "version": "1.1.0", 227 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", 228 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", 229 | "dev": true 230 | }, 231 | "colors": { 232 | "version": "1.0.3", 233 | "resolved": "http://registry.npmjs.org/colors/-/colors-1.0.3.tgz", 234 | "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", 235 | "dev": true 236 | }, 237 | "combined-stream": { 238 | "version": "1.0.7", 239 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", 240 | "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", 241 | "requires": { 242 | "delayed-stream": "~1.0.0" 243 | } 244 | }, 245 | "commander": { 246 | "version": "2.9.0", 247 | "resolved": "http://registry.npmjs.org/commander/-/commander-2.9.0.tgz", 248 | "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", 249 | "requires": { 250 | "graceful-readlink": ">= 1.0.0" 251 | } 252 | }, 253 | "concat-map": { 254 | "version": "0.0.1", 255 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 256 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 257 | }, 258 | "core-util-is": { 259 | "version": "1.0.2", 260 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 261 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 262 | }, 263 | "cryptiles": { 264 | "version": "2.0.5", 265 | "resolved": "http://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", 266 | "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", 267 | "requires": { 268 | "boom": "2.x.x" 269 | } 270 | }, 271 | "ctype": { 272 | "version": "0.5.3", 273 | "resolved": "http://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", 274 | "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=" 275 | }, 276 | "dashdash": { 277 | "version": "1.14.1", 278 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 279 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 280 | "dev": true, 281 | "requires": { 282 | "assert-plus": "^1.0.0" 283 | } 284 | }, 285 | "debug": { 286 | "version": "2.6.9", 287 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 288 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 289 | "dev": true, 290 | "requires": { 291 | "ms": "2.0.0" 292 | } 293 | }, 294 | "decamelize": { 295 | "version": "1.2.0", 296 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 297 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 298 | "dev": true 299 | }, 300 | "del": { 301 | "version": "0.1.3", 302 | "resolved": "https://registry.npmjs.org/del/-/del-0.1.3.tgz", 303 | "integrity": "sha1-LXJKcZtaz1wLhAtCJHFeg4QGpBk=", 304 | "requires": { 305 | "each-async": "^1.0.0", 306 | "globby": "^0.1.1", 307 | "is-path-cwd": "^1.0.0", 308 | "is-path-in-cwd": "^1.0.0", 309 | "rimraf": "^2.2.8" 310 | }, 311 | "dependencies": { 312 | "array-union": { 313 | "version": "0.1.0", 314 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-0.1.0.tgz", 315 | "integrity": "sha1-7emAiDMGZeaZ4evwIny8YDTmJ9s=", 316 | "requires": { 317 | "array-uniq": "^0.1.0" 318 | } 319 | }, 320 | "array-uniq": { 321 | "version": "0.1.1", 322 | "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-0.1.1.tgz", 323 | "integrity": "sha1-WGHz7U5LthdVl6TgeOiqeOvpWMc=" 324 | }, 325 | "glob": { 326 | "version": "4.5.3", 327 | "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", 328 | "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", 329 | "requires": { 330 | "inflight": "^1.0.4", 331 | "inherits": "2", 332 | "minimatch": "^2.0.1", 333 | "once": "^1.3.0" 334 | } 335 | }, 336 | "globby": { 337 | "version": "0.1.1", 338 | "resolved": "http://registry.npmjs.org/globby/-/globby-0.1.1.tgz", 339 | "integrity": "sha1-y+xj33JLS+pFi3mhbMDjsfLKhiA=", 340 | "requires": { 341 | "array-differ": "^0.1.0", 342 | "array-union": "^0.1.0", 343 | "async": "^0.9.0", 344 | "glob": "^4.0.2" 345 | } 346 | }, 347 | "minimatch": { 348 | "version": "2.0.10", 349 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", 350 | "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", 351 | "requires": { 352 | "brace-expansion": "^1.0.0" 353 | } 354 | } 355 | } 356 | }, 357 | "delayed-stream": { 358 | "version": "1.0.0", 359 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 360 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 361 | }, 362 | "dir-compare": { 363 | "version": "1.4.0", 364 | "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-1.4.0.tgz", 365 | "integrity": "sha1-r6AKuZwPscQStI3GXo9DeNJX8AY=", 366 | "dev": true, 367 | "requires": { 368 | "bluebird": "3.4.1", 369 | "buffer-equal": "1.0.0", 370 | "colors": "1.0.3", 371 | "commander": "2.9.0", 372 | "minimatch": "3.0.2" 373 | }, 374 | "dependencies": { 375 | "bluebird": { 376 | "version": "3.4.1", 377 | "resolved": "http://registry.npmjs.org/bluebird/-/bluebird-3.4.1.tgz", 378 | "integrity": "sha1-tzHd9I4t077awudeEhWhG8uR+gc=", 379 | "dev": true 380 | } 381 | } 382 | }, 383 | "each-async": { 384 | "version": "1.1.1", 385 | "resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz", 386 | "integrity": "sha1-3uUim98KtrogEqOV4bhpq/iBNHM=", 387 | "requires": { 388 | "onetime": "^1.0.0", 389 | "set-immediate-shim": "^1.0.0" 390 | } 391 | }, 392 | "ecc-jsbn": { 393 | "version": "0.1.2", 394 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 395 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 396 | "dev": true, 397 | "requires": { 398 | "jsbn": "~0.1.0", 399 | "safer-buffer": "^2.1.0" 400 | } 401 | }, 402 | "error-ex": { 403 | "version": "1.3.2", 404 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", 405 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", 406 | "dev": true, 407 | "requires": { 408 | "is-arrayish": "^0.2.1" 409 | } 410 | }, 411 | "escape-string-regexp": { 412 | "version": "1.0.5", 413 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 414 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 415 | }, 416 | "extend": { 417 | "version": "3.0.2", 418 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 419 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 420 | }, 421 | "extsprintf": { 422 | "version": "1.3.0", 423 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 424 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", 425 | "dev": true 426 | }, 427 | "fast-deep-equal": { 428 | "version": "2.0.1", 429 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", 430 | "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", 431 | "dev": true 432 | }, 433 | "fast-json-stable-stringify": { 434 | "version": "2.0.0", 435 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 436 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", 437 | "dev": true 438 | }, 439 | "find-up": { 440 | "version": "1.1.2", 441 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", 442 | "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", 443 | "dev": true, 444 | "requires": { 445 | "path-exists": "^2.0.0", 446 | "pinkie-promise": "^2.0.0" 447 | } 448 | }, 449 | "forever-agent": { 450 | "version": "0.6.1", 451 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 452 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" 453 | }, 454 | "form-data": { 455 | "version": "2.3.3", 456 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 457 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 458 | "dev": true, 459 | "requires": { 460 | "asynckit": "^0.4.0", 461 | "combined-stream": "^1.0.6", 462 | "mime-types": "^2.1.12" 463 | } 464 | }, 465 | "fs-extra": { 466 | "version": "3.0.1", 467 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", 468 | "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", 469 | "dev": true, 470 | "requires": { 471 | "graceful-fs": "^4.1.2", 472 | "jsonfile": "^3.0.0", 473 | "universalify": "^0.1.0" 474 | } 475 | }, 476 | "fs.realpath": { 477 | "version": "1.0.0", 478 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 479 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 480 | }, 481 | "fstream": { 482 | "version": "0.1.31", 483 | "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", 484 | "integrity": "sha1-czfwWPu7vvqMn1YaKMqwhJICyYg=", 485 | "requires": { 486 | "graceful-fs": "~3.0.2", 487 | "inherits": "~2.0.0", 488 | "mkdirp": "0.5", 489 | "rimraf": "2" 490 | }, 491 | "dependencies": { 492 | "graceful-fs": { 493 | "version": "3.0.11", 494 | "resolved": "http://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", 495 | "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", 496 | "requires": { 497 | "natives": "^1.1.0" 498 | } 499 | } 500 | } 501 | }, 502 | "generate-function": { 503 | "version": "2.3.1", 504 | "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", 505 | "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", 506 | "requires": { 507 | "is-property": "^1.0.2" 508 | } 509 | }, 510 | "generate-object-property": { 511 | "version": "1.2.0", 512 | "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", 513 | "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", 514 | "requires": { 515 | "is-property": "^1.0.0" 516 | } 517 | }, 518 | "get-caller-file": { 519 | "version": "1.0.3", 520 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", 521 | "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", 522 | "dev": true 523 | }, 524 | "getpass": { 525 | "version": "0.1.7", 526 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 527 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 528 | "dev": true, 529 | "requires": { 530 | "assert-plus": "^1.0.0" 531 | } 532 | }, 533 | "glob": { 534 | "version": "7.1.3", 535 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", 536 | "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", 537 | "requires": { 538 | "fs.realpath": "^1.0.0", 539 | "inflight": "^1.0.4", 540 | "inherits": "2", 541 | "minimatch": "^3.0.4", 542 | "once": "^1.3.0", 543 | "path-is-absolute": "^1.0.0" 544 | }, 545 | "dependencies": { 546 | "minimatch": { 547 | "version": "3.0.4", 548 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 549 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 550 | "requires": { 551 | "brace-expansion": "^1.1.7" 552 | } 553 | } 554 | } 555 | }, 556 | "globby": { 557 | "version": "6.1.0", 558 | "resolved": "http://registry.npmjs.org/globby/-/globby-6.1.0.tgz", 559 | "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", 560 | "dev": true, 561 | "requires": { 562 | "array-union": "^1.0.1", 563 | "glob": "^7.0.3", 564 | "object-assign": "^4.0.1", 565 | "pify": "^2.0.0", 566 | "pinkie-promise": "^2.0.0" 567 | } 568 | }, 569 | "graceful-fs": { 570 | "version": "4.1.15", 571 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", 572 | "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", 573 | "dev": true 574 | }, 575 | "graceful-readlink": { 576 | "version": "1.0.1", 577 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", 578 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" 579 | }, 580 | "har-schema": { 581 | "version": "2.0.0", 582 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 583 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", 584 | "dev": true 585 | }, 586 | "har-validator": { 587 | "version": "5.1.3", 588 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", 589 | "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", 590 | "dev": true, 591 | "requires": { 592 | "ajv": "^6.5.5", 593 | "har-schema": "^2.0.0" 594 | } 595 | }, 596 | "has-ansi": { 597 | "version": "2.0.0", 598 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 599 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 600 | "requires": { 601 | "ansi-regex": "^2.0.0" 602 | } 603 | }, 604 | "hawk": { 605 | "version": "3.1.3", 606 | "resolved": "http://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", 607 | "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", 608 | "requires": { 609 | "boom": "2.x.x", 610 | "cryptiles": "2.x.x", 611 | "hoek": "2.x.x", 612 | "sntp": "1.x.x" 613 | } 614 | }, 615 | "hoek": { 616 | "version": "2.16.3", 617 | "resolved": "http://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", 618 | "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" 619 | }, 620 | "hosted-git-info": { 621 | "version": "2.7.1", 622 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", 623 | "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", 624 | "dev": true 625 | }, 626 | "http-signature": { 627 | "version": "1.2.0", 628 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 629 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 630 | "dev": true, 631 | "requires": { 632 | "assert-plus": "^1.0.0", 633 | "jsprim": "^1.2.2", 634 | "sshpk": "^1.7.0" 635 | } 636 | }, 637 | "iconv-lite": { 638 | "version": "0.4.24", 639 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 640 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 641 | "requires": { 642 | "safer-buffer": ">= 2.1.2 < 3" 643 | } 644 | }, 645 | "inflight": { 646 | "version": "1.0.6", 647 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 648 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 649 | "requires": { 650 | "once": "^1.3.0", 651 | "wrappy": "1" 652 | } 653 | }, 654 | "inherits": { 655 | "version": "2.0.3", 656 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 657 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 658 | }, 659 | "invert-kv": { 660 | "version": "1.0.0", 661 | "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", 662 | "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", 663 | "dev": true 664 | }, 665 | "is-arrayish": { 666 | "version": "0.2.1", 667 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 668 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", 669 | "dev": true 670 | }, 671 | "is-builtin-module": { 672 | "version": "1.0.0", 673 | "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", 674 | "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", 675 | "dev": true, 676 | "requires": { 677 | "builtin-modules": "^1.0.0" 678 | } 679 | }, 680 | "is-fullwidth-code-point": { 681 | "version": "1.0.0", 682 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 683 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 684 | "dev": true, 685 | "requires": { 686 | "number-is-nan": "^1.0.0" 687 | } 688 | }, 689 | "is-my-ip-valid": { 690 | "version": "1.0.0", 691 | "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", 692 | "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==" 693 | }, 694 | "is-my-json-valid": { 695 | "version": "2.19.0", 696 | "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz", 697 | "integrity": "sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==", 698 | "requires": { 699 | "generate-function": "^2.0.0", 700 | "generate-object-property": "^1.1.0", 701 | "is-my-ip-valid": "^1.0.0", 702 | "jsonpointer": "^4.0.0", 703 | "xtend": "^4.0.0" 704 | } 705 | }, 706 | "is-path-cwd": { 707 | "version": "1.0.0", 708 | "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", 709 | "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" 710 | }, 711 | "is-path-in-cwd": { 712 | "version": "1.0.1", 713 | "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", 714 | "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", 715 | "requires": { 716 | "is-path-inside": "^1.0.0" 717 | } 718 | }, 719 | "is-path-inside": { 720 | "version": "1.0.1", 721 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", 722 | "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", 723 | "requires": { 724 | "path-is-inside": "^1.0.1" 725 | } 726 | }, 727 | "is-property": { 728 | "version": "1.0.2", 729 | "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", 730 | "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" 731 | }, 732 | "is-typedarray": { 733 | "version": "1.0.0", 734 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 735 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 736 | "dev": true 737 | }, 738 | "is-utf8": { 739 | "version": "0.2.1", 740 | "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", 741 | "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", 742 | "dev": true 743 | }, 744 | "isarray": { 745 | "version": "1.0.0", 746 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 747 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 748 | }, 749 | "isstream": { 750 | "version": "0.1.2", 751 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 752 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 753 | }, 754 | "jsbn": { 755 | "version": "0.1.1", 756 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 757 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", 758 | "dev": true 759 | }, 760 | "json-schema": { 761 | "version": "0.2.3", 762 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 763 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", 764 | "dev": true 765 | }, 766 | "json-schema-traverse": { 767 | "version": "0.4.1", 768 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 769 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 770 | "dev": true 771 | }, 772 | "json-stringify-safe": { 773 | "version": "5.0.1", 774 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 775 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 776 | }, 777 | "jsonfile": { 778 | "version": "3.0.1", 779 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", 780 | "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", 781 | "dev": true, 782 | "requires": { 783 | "graceful-fs": "^4.1.6" 784 | } 785 | }, 786 | "jsonpointer": { 787 | "version": "4.0.1", 788 | "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", 789 | "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=" 790 | }, 791 | "jsprim": { 792 | "version": "1.4.1", 793 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 794 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 795 | "dev": true, 796 | "requires": { 797 | "assert-plus": "1.0.0", 798 | "extsprintf": "1.3.0", 799 | "json-schema": "0.2.3", 800 | "verror": "1.10.0" 801 | } 802 | }, 803 | "keypress": { 804 | "version": "0.1.0", 805 | "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz", 806 | "integrity": "sha1-SjGI1CkbZrT2XtuZ+AaqmuKTWSo=" 807 | }, 808 | "lcid": { 809 | "version": "1.0.0", 810 | "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", 811 | "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", 812 | "dev": true, 813 | "requires": { 814 | "invert-kv": "^1.0.0" 815 | } 816 | }, 817 | "load-json-file": { 818 | "version": "1.1.0", 819 | "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", 820 | "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", 821 | "dev": true, 822 | "requires": { 823 | "graceful-fs": "^4.1.2", 824 | "parse-json": "^2.2.0", 825 | "pify": "^2.0.0", 826 | "pinkie-promise": "^2.0.0", 827 | "strip-bom": "^2.0.0" 828 | } 829 | }, 830 | "lodash": { 831 | "version": "4.17.11", 832 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", 833 | "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" 834 | }, 835 | "mime-db": { 836 | "version": "1.37.0", 837 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", 838 | "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" 839 | }, 840 | "mime-types": { 841 | "version": "2.1.21", 842 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", 843 | "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", 844 | "requires": { 845 | "mime-db": "~1.37.0" 846 | } 847 | }, 848 | "minimatch": { 849 | "version": "3.0.2", 850 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz", 851 | "integrity": "sha1-DzmKcwDqRB6cNIyD2Yq4ydv5xAo=", 852 | "dev": true, 853 | "requires": { 854 | "brace-expansion": "^1.0.0" 855 | } 856 | }, 857 | "minimist": { 858 | "version": "0.0.8", 859 | "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 860 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 861 | }, 862 | "mkdirp": { 863 | "version": "0.5.1", 864 | "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 865 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 866 | "requires": { 867 | "minimist": "0.0.8" 868 | } 869 | }, 870 | "ms": { 871 | "version": "2.0.0", 872 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 873 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 874 | "dev": true 875 | }, 876 | "mutable-buffer": { 877 | "version": "2.1.1", 878 | "resolved": "https://registry.npmjs.org/mutable-buffer/-/mutable-buffer-2.1.1.tgz", 879 | "integrity": "sha512-fKlBJ3DJh3lVwdkR96FyvqxW8vswhk2KthgK55ZQv3DrGzllvmTWjKRSgS9sJMr+b7zjWFV8q/pHLR42ADCxtg==" 880 | }, 881 | "natives": { 882 | "version": "1.1.6", 883 | "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz", 884 | "integrity": "sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==" 885 | }, 886 | "ncp": { 887 | "version": "2.0.0", 888 | "resolved": "http://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", 889 | "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=" 890 | }, 891 | "node-webkit-updater": { 892 | "version": "0.3.3", 893 | "resolved": "https://registry.npmjs.org/node-webkit-updater/-/node-webkit-updater-0.3.3.tgz", 894 | "integrity": "sha1-IYV5wiUSO4KJWXseNGirbop4mIg=", 895 | "requires": { 896 | "del": "~0.1.2", 897 | "ncp": "2.0.0", 898 | "request": "~2.64.0", 899 | "semver": "^5.0.3", 900 | "tar.gz": "^0.1.1" 901 | }, 902 | "dependencies": { 903 | "asn1": { 904 | "version": "0.1.11", 905 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", 906 | "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=" 907 | }, 908 | "assert-plus": { 909 | "version": "0.1.5", 910 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", 911 | "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=" 912 | }, 913 | "async": { 914 | "version": "2.6.1", 915 | "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", 916 | "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", 917 | "requires": { 918 | "lodash": "^4.17.10" 919 | } 920 | }, 921 | "aws-sign2": { 922 | "version": "0.5.0", 923 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", 924 | "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=" 925 | }, 926 | "bluebird": { 927 | "version": "2.11.0", 928 | "resolved": "http://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", 929 | "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=" 930 | }, 931 | "caseless": { 932 | "version": "0.11.0", 933 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", 934 | "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=" 935 | }, 936 | "form-data": { 937 | "version": "1.0.1", 938 | "resolved": "http://registry.npmjs.org/form-data/-/form-data-1.0.1.tgz", 939 | "integrity": "sha1-rjFduaSQf6BlUCMEpm13M0de43w=", 940 | "requires": { 941 | "async": "^2.0.1", 942 | "combined-stream": "^1.0.5", 943 | "mime-types": "^2.1.11" 944 | } 945 | }, 946 | "har-validator": { 947 | "version": "1.8.0", 948 | "resolved": "http://registry.npmjs.org/har-validator/-/har-validator-1.8.0.tgz", 949 | "integrity": "sha1-2DhCsOtMQ1lgrrEIoGejqpTA7rI=", 950 | "requires": { 951 | "bluebird": "^2.9.30", 952 | "chalk": "^1.0.0", 953 | "commander": "^2.8.1", 954 | "is-my-json-valid": "^2.12.0" 955 | } 956 | }, 957 | "http-signature": { 958 | "version": "0.11.0", 959 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.11.0.tgz", 960 | "integrity": "sha1-F5bPZ6ABrVzWhJ3KCZFIXwkIn+Y=", 961 | "requires": { 962 | "asn1": "0.1.11", 963 | "assert-plus": "^0.1.5", 964 | "ctype": "0.5.3" 965 | } 966 | }, 967 | "node-uuid": { 968 | "version": "1.4.8", 969 | "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", 970 | "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=" 971 | }, 972 | "oauth-sign": { 973 | "version": "0.8.2", 974 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", 975 | "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" 976 | }, 977 | "qs": { 978 | "version": "5.1.0", 979 | "resolved": "http://registry.npmjs.org/qs/-/qs-5.1.0.tgz", 980 | "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=" 981 | }, 982 | "request": { 983 | "version": "2.64.0", 984 | "resolved": "http://registry.npmjs.org/request/-/request-2.64.0.tgz", 985 | "integrity": "sha1-lqWCQjzptLXDTpsjLkgBc/FLpgg=", 986 | "requires": { 987 | "aws-sign2": "~0.5.0", 988 | "bl": "~1.0.0", 989 | "caseless": "~0.11.0", 990 | "combined-stream": "~1.0.1", 991 | "extend": "~3.0.0", 992 | "forever-agent": "~0.6.0", 993 | "form-data": "~1.0.0-rc1", 994 | "har-validator": "^1.6.1", 995 | "hawk": "~3.1.0", 996 | "http-signature": "~0.11.0", 997 | "isstream": "~0.1.1", 998 | "json-stringify-safe": "~5.0.0", 999 | "mime-types": "~2.1.2", 1000 | "node-uuid": "~1.4.0", 1001 | "oauth-sign": "~0.8.0", 1002 | "qs": "~5.1.0", 1003 | "stringstream": "~0.0.4", 1004 | "tough-cookie": ">=0.12.0", 1005 | "tunnel-agent": "~0.4.0" 1006 | } 1007 | }, 1008 | "tunnel-agent": { 1009 | "version": "0.4.3", 1010 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", 1011 | "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=" 1012 | } 1013 | } 1014 | }, 1015 | "normalize-package-data": { 1016 | "version": "2.4.0", 1017 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", 1018 | "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", 1019 | "dev": true, 1020 | "requires": { 1021 | "hosted-git-info": "^2.1.4", 1022 | "is-builtin-module": "^1.0.0", 1023 | "semver": "2 || 3 || 4 || 5", 1024 | "validate-npm-package-license": "^3.0.1" 1025 | } 1026 | }, 1027 | "number-is-nan": { 1028 | "version": "1.0.1", 1029 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 1030 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", 1031 | "dev": true 1032 | }, 1033 | "nwjs-builder-phoenix": { 1034 | "version": "1.14.8", 1035 | "resolved": "https://registry.npmjs.org/nwjs-builder-phoenix/-/nwjs-builder-phoenix-1.14.8.tgz", 1036 | "integrity": "sha512-/U2riCQDRn9jbZaKV7pSyJCBIR+/h8OhkXGwTmA8nDHsSPYMF4c8EVZoiBWiUDI3ztOWKdoQvLgc0DMe6MWRGw==", 1037 | "dev": true, 1038 | "requires": { 1039 | "7zip-bin": "^2.0.4", 1040 | "bluebird": "^3.5.0", 1041 | "debug": "^2.6.1", 1042 | "dir-compare": "^1.3.0", 1043 | "fs-extra": "^3.0.1", 1044 | "globby": "^6.1.0", 1045 | "plist": "^2.0.1", 1046 | "progress": "^1.1.8", 1047 | "rcedit": "^0.8.0", 1048 | "request": "^2.80.0", 1049 | "request-progress": "^3.0.0", 1050 | "semver": "^5.3.0", 1051 | "source-map-support": "^0.4.11", 1052 | "tmp": "0.0.31", 1053 | "yargs": "^7.0.1" 1054 | } 1055 | }, 1056 | "oauth-sign": { 1057 | "version": "0.9.0", 1058 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 1059 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", 1060 | "dev": true 1061 | }, 1062 | "object-assign": { 1063 | "version": "4.1.1", 1064 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1065 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", 1066 | "dev": true 1067 | }, 1068 | "once": { 1069 | "version": "1.4.0", 1070 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1071 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1072 | "requires": { 1073 | "wrappy": "1" 1074 | } 1075 | }, 1076 | "onetime": { 1077 | "version": "1.1.0", 1078 | "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", 1079 | "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" 1080 | }, 1081 | "os-locale": { 1082 | "version": "1.4.0", 1083 | "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", 1084 | "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", 1085 | "dev": true, 1086 | "requires": { 1087 | "lcid": "^1.0.0" 1088 | } 1089 | }, 1090 | "os-tmpdir": { 1091 | "version": "1.0.2", 1092 | "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 1093 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", 1094 | "dev": true 1095 | }, 1096 | "parse-json": { 1097 | "version": "2.2.0", 1098 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", 1099 | "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", 1100 | "dev": true, 1101 | "requires": { 1102 | "error-ex": "^1.2.0" 1103 | } 1104 | }, 1105 | "path-exists": { 1106 | "version": "2.1.0", 1107 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", 1108 | "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", 1109 | "dev": true, 1110 | "requires": { 1111 | "pinkie-promise": "^2.0.0" 1112 | } 1113 | }, 1114 | "path-is-absolute": { 1115 | "version": "1.0.1", 1116 | "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1117 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 1118 | }, 1119 | "path-is-inside": { 1120 | "version": "1.0.2", 1121 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", 1122 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" 1123 | }, 1124 | "path-type": { 1125 | "version": "1.1.0", 1126 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", 1127 | "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", 1128 | "dev": true, 1129 | "requires": { 1130 | "graceful-fs": "^4.1.2", 1131 | "pify": "^2.0.0", 1132 | "pinkie-promise": "^2.0.0" 1133 | } 1134 | }, 1135 | "performance-now": { 1136 | "version": "2.1.0", 1137 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 1138 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", 1139 | "dev": true 1140 | }, 1141 | "pify": { 1142 | "version": "2.3.0", 1143 | "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 1144 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", 1145 | "dev": true 1146 | }, 1147 | "pinkie": { 1148 | "version": "2.0.4", 1149 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", 1150 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", 1151 | "dev": true 1152 | }, 1153 | "pinkie-promise": { 1154 | "version": "2.0.1", 1155 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", 1156 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", 1157 | "dev": true, 1158 | "requires": { 1159 | "pinkie": "^2.0.0" 1160 | } 1161 | }, 1162 | "plist": { 1163 | "version": "2.1.0", 1164 | "resolved": "https://registry.npmjs.org/plist/-/plist-2.1.0.tgz", 1165 | "integrity": "sha1-V8zbeggh3yGDEhejytVOPhRqECU=", 1166 | "dev": true, 1167 | "requires": { 1168 | "base64-js": "1.2.0", 1169 | "xmlbuilder": "8.2.2", 1170 | "xmldom": "0.1.x" 1171 | } 1172 | }, 1173 | "printer": { 1174 | "version": "0.2.2", 1175 | "resolved": "https://registry.npmjs.org/printer/-/printer-0.2.2.tgz", 1176 | "integrity": "sha1-gwuPXJe5f9m0ZNT04QXUMzd5IpY=" 1177 | }, 1178 | "process-nextick-args": { 1179 | "version": "1.0.7", 1180 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", 1181 | "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" 1182 | }, 1183 | "progress": { 1184 | "version": "1.1.8", 1185 | "resolved": "http://registry.npmjs.org/progress/-/progress-1.1.8.tgz", 1186 | "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", 1187 | "dev": true 1188 | }, 1189 | "psl": { 1190 | "version": "1.1.29", 1191 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", 1192 | "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" 1193 | }, 1194 | "punycode": { 1195 | "version": "2.1.1", 1196 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1197 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 1198 | "dev": true 1199 | }, 1200 | "qs": { 1201 | "version": "6.5.2", 1202 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 1203 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", 1204 | "dev": true 1205 | }, 1206 | "rcedit": { 1207 | "version": "0.8.0", 1208 | "resolved": "https://registry.npmjs.org/rcedit/-/rcedit-0.8.0.tgz", 1209 | "integrity": "sha1-3DEwrrAo9KZYrC48jm0EciLayUg=", 1210 | "dev": true 1211 | }, 1212 | "read-pkg": { 1213 | "version": "1.1.0", 1214 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", 1215 | "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", 1216 | "dev": true, 1217 | "requires": { 1218 | "load-json-file": "^1.0.0", 1219 | "normalize-package-data": "^2.3.2", 1220 | "path-type": "^1.0.0" 1221 | } 1222 | }, 1223 | "read-pkg-up": { 1224 | "version": "1.0.1", 1225 | "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", 1226 | "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", 1227 | "dev": true, 1228 | "requires": { 1229 | "find-up": "^1.0.0", 1230 | "read-pkg": "^1.0.0" 1231 | } 1232 | }, 1233 | "readable-stream": { 1234 | "version": "2.0.6", 1235 | "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", 1236 | "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", 1237 | "requires": { 1238 | "core-util-is": "~1.0.0", 1239 | "inherits": "~2.0.1", 1240 | "isarray": "~1.0.0", 1241 | "process-nextick-args": "~1.0.6", 1242 | "string_decoder": "~0.10.x", 1243 | "util-deprecate": "~1.0.1" 1244 | } 1245 | }, 1246 | "request": { 1247 | "version": "2.88.0", 1248 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", 1249 | "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", 1250 | "dev": true, 1251 | "requires": { 1252 | "aws-sign2": "~0.7.0", 1253 | "aws4": "^1.8.0", 1254 | "caseless": "~0.12.0", 1255 | "combined-stream": "~1.0.6", 1256 | "extend": "~3.0.2", 1257 | "forever-agent": "~0.6.1", 1258 | "form-data": "~2.3.2", 1259 | "har-validator": "~5.1.0", 1260 | "http-signature": "~1.2.0", 1261 | "is-typedarray": "~1.0.0", 1262 | "isstream": "~0.1.2", 1263 | "json-stringify-safe": "~5.0.1", 1264 | "mime-types": "~2.1.19", 1265 | "oauth-sign": "~0.9.0", 1266 | "performance-now": "^2.1.0", 1267 | "qs": "~6.5.2", 1268 | "safe-buffer": "^5.1.2", 1269 | "tough-cookie": "~2.4.3", 1270 | "tunnel-agent": "^0.6.0", 1271 | "uuid": "^3.3.2" 1272 | } 1273 | }, 1274 | "request-progress": { 1275 | "version": "3.0.0", 1276 | "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", 1277 | "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=", 1278 | "dev": true, 1279 | "requires": { 1280 | "throttleit": "^1.0.0" 1281 | } 1282 | }, 1283 | "require-directory": { 1284 | "version": "2.1.1", 1285 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1286 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 1287 | "dev": true 1288 | }, 1289 | "require-main-filename": { 1290 | "version": "1.0.1", 1291 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", 1292 | "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", 1293 | "dev": true 1294 | }, 1295 | "rimraf": { 1296 | "version": "2.6.2", 1297 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", 1298 | "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", 1299 | "requires": { 1300 | "glob": "^7.0.5" 1301 | } 1302 | }, 1303 | "safe-buffer": { 1304 | "version": "5.1.2", 1305 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1306 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 1307 | "dev": true 1308 | }, 1309 | "safer-buffer": { 1310 | "version": "2.1.2", 1311 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1312 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1313 | }, 1314 | "semver": { 1315 | "version": "5.6.0", 1316 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", 1317 | "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" 1318 | }, 1319 | "set-blocking": { 1320 | "version": "2.0.0", 1321 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 1322 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 1323 | "dev": true 1324 | }, 1325 | "set-immediate-shim": { 1326 | "version": "1.0.1", 1327 | "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", 1328 | "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" 1329 | }, 1330 | "sntp": { 1331 | "version": "1.0.9", 1332 | "resolved": "http://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", 1333 | "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", 1334 | "requires": { 1335 | "hoek": "2.x.x" 1336 | } 1337 | }, 1338 | "source-map": { 1339 | "version": "0.5.7", 1340 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1341 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 1342 | "dev": true 1343 | }, 1344 | "source-map-support": { 1345 | "version": "0.4.18", 1346 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", 1347 | "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", 1348 | "dev": true, 1349 | "requires": { 1350 | "source-map": "^0.5.6" 1351 | } 1352 | }, 1353 | "spdx-correct": { 1354 | "version": "3.0.2", 1355 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", 1356 | "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", 1357 | "dev": true, 1358 | "requires": { 1359 | "spdx-expression-parse": "^3.0.0", 1360 | "spdx-license-ids": "^3.0.0" 1361 | } 1362 | }, 1363 | "spdx-exceptions": { 1364 | "version": "2.2.0", 1365 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", 1366 | "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", 1367 | "dev": true 1368 | }, 1369 | "spdx-expression-parse": { 1370 | "version": "3.0.0", 1371 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", 1372 | "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", 1373 | "dev": true, 1374 | "requires": { 1375 | "spdx-exceptions": "^2.1.0", 1376 | "spdx-license-ids": "^3.0.0" 1377 | } 1378 | }, 1379 | "spdx-license-ids": { 1380 | "version": "3.0.2", 1381 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz", 1382 | "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==", 1383 | "dev": true 1384 | }, 1385 | "sprintf-js": { 1386 | "version": "1.1.1", 1387 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", 1388 | "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=" 1389 | }, 1390 | "sshpk": { 1391 | "version": "1.15.2", 1392 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", 1393 | "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", 1394 | "dev": true, 1395 | "requires": { 1396 | "asn1": "~0.2.3", 1397 | "assert-plus": "^1.0.0", 1398 | "bcrypt-pbkdf": "^1.0.0", 1399 | "dashdash": "^1.12.0", 1400 | "ecc-jsbn": "~0.1.1", 1401 | "getpass": "^0.1.1", 1402 | "jsbn": "~0.1.0", 1403 | "safer-buffer": "^2.0.2", 1404 | "tweetnacl": "~0.14.0" 1405 | } 1406 | }, 1407 | "string-width": { 1408 | "version": "1.0.2", 1409 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 1410 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 1411 | "dev": true, 1412 | "requires": { 1413 | "code-point-at": "^1.0.0", 1414 | "is-fullwidth-code-point": "^1.0.0", 1415 | "strip-ansi": "^3.0.0" 1416 | } 1417 | }, 1418 | "string_decoder": { 1419 | "version": "0.10.31", 1420 | "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 1421 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" 1422 | }, 1423 | "stringstream": { 1424 | "version": "0.0.6", 1425 | "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", 1426 | "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==" 1427 | }, 1428 | "strip-ansi": { 1429 | "version": "3.0.1", 1430 | "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 1431 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 1432 | "requires": { 1433 | "ansi-regex": "^2.0.0" 1434 | } 1435 | }, 1436 | "strip-bom": { 1437 | "version": "2.0.0", 1438 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", 1439 | "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", 1440 | "dev": true, 1441 | "requires": { 1442 | "is-utf8": "^0.2.0" 1443 | } 1444 | }, 1445 | "supports-color": { 1446 | "version": "2.0.0", 1447 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 1448 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" 1449 | }, 1450 | "tar": { 1451 | "version": "0.1.20", 1452 | "resolved": "http://registry.npmjs.org/tar/-/tar-0.1.20.tgz", 1453 | "integrity": "sha1-QpQLrltfIsdEg2mRJvnz8nRJyxM=", 1454 | "requires": { 1455 | "block-stream": "*", 1456 | "fstream": "~0.1.28", 1457 | "inherits": "2" 1458 | } 1459 | }, 1460 | "tar.gz": { 1461 | "version": "0.1.1", 1462 | "resolved": "https://registry.npmjs.org/tar.gz/-/tar.gz-0.1.1.tgz", 1463 | "integrity": "sha1-6RTOI7L9xidXX72zSFpbIo7VmUc=", 1464 | "requires": { 1465 | "commander": "1.1.x", 1466 | "fstream": "0.1.x", 1467 | "tar": "0.1.x" 1468 | }, 1469 | "dependencies": { 1470 | "commander": { 1471 | "version": "1.1.1", 1472 | "resolved": "http://registry.npmjs.org/commander/-/commander-1.1.1.tgz", 1473 | "integrity": "sha1-UNFlGGiuYOzP8KLZ80WVN2vGsEE=", 1474 | "requires": { 1475 | "keypress": "0.1.x" 1476 | } 1477 | } 1478 | } 1479 | }, 1480 | "throttleit": { 1481 | "version": "1.0.0", 1482 | "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", 1483 | "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", 1484 | "dev": true 1485 | }, 1486 | "tmp": { 1487 | "version": "0.0.31", 1488 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", 1489 | "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", 1490 | "dev": true, 1491 | "requires": { 1492 | "os-tmpdir": "~1.0.1" 1493 | } 1494 | }, 1495 | "tough-cookie": { 1496 | "version": "2.4.3", 1497 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", 1498 | "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", 1499 | "requires": { 1500 | "psl": "^1.1.24", 1501 | "punycode": "^1.4.1" 1502 | }, 1503 | "dependencies": { 1504 | "punycode": { 1505 | "version": "1.4.1", 1506 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 1507 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" 1508 | } 1509 | } 1510 | }, 1511 | "tunnel-agent": { 1512 | "version": "0.6.0", 1513 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 1514 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 1515 | "dev": true, 1516 | "requires": { 1517 | "safe-buffer": "^5.0.1" 1518 | } 1519 | }, 1520 | "tweetnacl": { 1521 | "version": "0.14.5", 1522 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 1523 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", 1524 | "dev": true 1525 | }, 1526 | "universalify": { 1527 | "version": "0.1.2", 1528 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 1529 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", 1530 | "dev": true 1531 | }, 1532 | "uri-js": { 1533 | "version": "4.2.2", 1534 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 1535 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 1536 | "dev": true, 1537 | "requires": { 1538 | "punycode": "^2.1.0" 1539 | } 1540 | }, 1541 | "util-deprecate": { 1542 | "version": "1.0.2", 1543 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1544 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1545 | }, 1546 | "uuid": { 1547 | "version": "3.3.2", 1548 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 1549 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", 1550 | "dev": true 1551 | }, 1552 | "validate-npm-package-license": { 1553 | "version": "3.0.4", 1554 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", 1555 | "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", 1556 | "dev": true, 1557 | "requires": { 1558 | "spdx-correct": "^3.0.0", 1559 | "spdx-expression-parse": "^3.0.0" 1560 | } 1561 | }, 1562 | "verror": { 1563 | "version": "1.10.0", 1564 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 1565 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 1566 | "dev": true, 1567 | "requires": { 1568 | "assert-plus": "^1.0.0", 1569 | "core-util-is": "1.0.2", 1570 | "extsprintf": "^1.2.0" 1571 | } 1572 | }, 1573 | "which-module": { 1574 | "version": "1.0.0", 1575 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", 1576 | "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", 1577 | "dev": true 1578 | }, 1579 | "wrap-ansi": { 1580 | "version": "2.1.0", 1581 | "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", 1582 | "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", 1583 | "dev": true, 1584 | "requires": { 1585 | "string-width": "^1.0.1", 1586 | "strip-ansi": "^3.0.1" 1587 | } 1588 | }, 1589 | "wrappy": { 1590 | "version": "1.0.2", 1591 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1592 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 1593 | }, 1594 | "xmlbuilder": { 1595 | "version": "8.2.2", 1596 | "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", 1597 | "integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=", 1598 | "dev": true 1599 | }, 1600 | "xmldom": { 1601 | "version": "0.1.27", 1602 | "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", 1603 | "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=", 1604 | "dev": true 1605 | }, 1606 | "xtend": { 1607 | "version": "4.0.1", 1608 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", 1609 | "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" 1610 | }, 1611 | "y18n": { 1612 | "version": "3.2.1", 1613 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", 1614 | "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", 1615 | "dev": true 1616 | }, 1617 | "yargs": { 1618 | "version": "7.1.0", 1619 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", 1620 | "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", 1621 | "dev": true, 1622 | "requires": { 1623 | "camelcase": "^3.0.0", 1624 | "cliui": "^3.2.0", 1625 | "decamelize": "^1.1.1", 1626 | "get-caller-file": "^1.0.1", 1627 | "os-locale": "^1.4.0", 1628 | "read-pkg-up": "^1.0.1", 1629 | "require-directory": "^2.1.1", 1630 | "require-main-filename": "^1.0.1", 1631 | "set-blocking": "^2.0.0", 1632 | "string-width": "^1.0.2", 1633 | "which-module": "^1.0.0", 1634 | "y18n": "^3.2.1", 1635 | "yargs-parser": "^5.0.0" 1636 | } 1637 | }, 1638 | "yargs-parser": { 1639 | "version": "5.0.0", 1640 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", 1641 | "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", 1642 | "dev": true, 1643 | "requires": { 1644 | "camelcase": "^3.0.0" 1645 | } 1646 | } 1647 | } 1648 | } 1649 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "all-embracing", 3 | "title": "万象集", 4 | "main": "index.html", 5 | "description": "An nw.js app", 6 | "version": "0.0.1", 7 | "scripts": { 8 | "dist": "build --tasks win-x64 --mirror https://npm.taobao.org/mirrors/nwjs/ .", 9 | "start": "run --x64 --mirror https://npm.taobao.org/mirrors/nwjs/ ." 10 | }, 11 | "manifestUrl": "http://sems-1254389369.cosgz.myqcloud.com/takeout_aggregate/update/package.json", 12 | "packages": { 13 | "win": { 14 | "url": "http://sems-1254389369.cosgz.myqcloud.com/takeout_aggregate/update/%E4%B8%87%E8%B1%A1%E9%9B%86.zip" 15 | } 16 | }, 17 | "license": "MIT", 18 | "repository": "https://github.com/LittlehorseXie/nw-printer", 19 | "single-instance": true, 20 | "build": { 21 | "appId": "sf.fe.all-embracing.project", 22 | "packed": false, 23 | "nwVersion": "0.32.0", 24 | "targets": [ 25 | "zip", 26 | "nsis7z" 27 | ], 28 | "strippedProperties": [ 29 | "build" 30 | ], 31 | "outputPattern": "${NAME} ${VERSION} ${PLATFORM} ${ARCH}", 32 | "win": { 33 | "productName": "万象集", 34 | "companyName": "sf", 35 | "copyright": "", 36 | "icon": "./assets/all.ico" 37 | }, 38 | "nsis": { 39 | "languages": [ 40 | "SimpChinese" 41 | ] 42 | } 43 | }, 44 | "window": { 45 | "icon": "./assets/all.png", 46 | "toolbar": true, 47 | "min_width": 1000, 48 | "min_height": 500, 49 | "single-instance": false 50 | }, 51 | "devDependencies": { 52 | "nwjs-builder-phoenix": "^1.14.8" 53 | }, 54 | "dependencies": { 55 | "iconv-lite": "^0.4.24", 56 | "mutable-buffer": "^2.1.1", 57 | "node-webkit-updater": "^0.3.3", 58 | "printer": "^0.2.2", 59 | "sprintf-js": "^1.1.1" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /printer.js: -------------------------------------------------------------------------------- 1 | const printer = nw.require('printer') 2 | 3 | module.exports = { 4 | /** 5 | * @returns {Array} 返回打印机列表 6 | */ 7 | getPrinterList: function() { 8 | return printer.getPrinters() 9 | }, 10 | /** 11 | * 调用打印功能 12 | * @param {string} printerName 打印机名称,可以由getPrinterList获取 13 | * @param {buffer} buffer 打印内容的buffer串 14 | */ 15 | print: function(printerName, buffer) { 16 | printer.printDirect({ 17 | data: buffer, 18 | printer: printerName, 19 | type: "RAW", 20 | success:function(jobID){ 21 | console.log("sent to printer with ID: "+jobID) 22 | }, 23 | error:function(err){ 24 | console.log(err) 25 | } 26 | }) 27 | }, 28 | /** 29 | * 判断当前打印机是否连接成功 30 | * @param {string} printerName 打印机名称,可以由getPrinterList获取 31 | */ 32 | getPrinter: function(printerName) { 33 | try{ 34 | printer.getPrinter(printerName) 35 | } catch(e) { 36 | return false 37 | } 38 | return true 39 | } 40 | } 41 | --------------------------------------------------------------------------------