Refactor public api
This commit is contained in:
parent
8fb9d0bb88
commit
0d6129737e
4 changed files with 114 additions and 397 deletions
|
@ -11,7 +11,7 @@ var file = process.argv[3]
|
|||
|
||||
if (text && text.length) {
|
||||
if (file && file.length) {
|
||||
qr.save(file, text, function (err, data) {
|
||||
qr.toFile(file, text, function (err, data) {
|
||||
if (!err) {
|
||||
process.stdout.write('saved qrcode to: ' + file + '\n')
|
||||
} else {
|
||||
|
@ -20,7 +20,7 @@ if (text && text.length) {
|
|||
}
|
||||
})
|
||||
} else {
|
||||
qr.drawText(text, function (error, text) {
|
||||
qr.toString(text, { type: 'terminal' }, function (error, text) {
|
||||
if (error) {
|
||||
throw new Error(error)
|
||||
}
|
||||
|
|
230
lib/index.js
230
lib/index.js
|
@ -9,232 +9,4 @@
|
|||
*
|
||||
*/
|
||||
|
||||
var QRCodeLib = require('./renderer/qrcode-draw')
|
||||
var terminalRender = require('./renderer/terminal')
|
||||
var svgRender = require('./renderer/svg')
|
||||
var Canvas = require('canvas')
|
||||
var fs = require('fs')
|
||||
|
||||
var QRCodeDraw = QRCodeLib.QRCodeDraw
|
||||
|
||||
// EXPORTS
|
||||
|
||||
//
|
||||
// breaking change to 0.1 this used to be an instance. now it returns the constructor.
|
||||
//
|
||||
exports.QRCodeDraw = QRCodeDraw
|
||||
|
||||
//
|
||||
// export error correct levels.
|
||||
//
|
||||
exports.errorCorrectLevels = QRCodeLib.QRErrorCorrectLevel
|
||||
|
||||
//
|
||||
// export original canvas to be used with draw method, esp. Canvas.Image
|
||||
//
|
||||
exports.canvas = Canvas
|
||||
|
||||
/*
|
||||
* provide an api to return the max characters allowed for given dimensions, and miniumum error correction level
|
||||
* the qr code library will always use the maximum error correction level for the given numbar of chars constrained by size
|
||||
*/
|
||||
exports.getMaxChars = function (minErrorCorrectionLevel, width, moduleScale) {
|
||||
// TODO THIS NEEDS TO WORK
|
||||
console.log('this doesnt work yet. comming soon =)')
|
||||
}
|
||||
|
||||
var parseOptions = function (options) {
|
||||
var textKeys = {
|
||||
'minimum': QRCodeLib.QRErrorCorrectLevel.L,
|
||||
'medium': QRCodeLib.QRErrorCorrectLevel.M,
|
||||
'high': QRCodeLib.QRErrorCorrectLevel.Q,
|
||||
'max': QRCodeLib.QRErrorCorrectLevel.H
|
||||
}
|
||||
|
||||
if (options.errorCorrectLevel) {
|
||||
var ec = options.errorCorrectLevel
|
||||
if (textKeys[ec]) {
|
||||
options.errorCorrectionLevel = textKeys[ec]
|
||||
}
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
// returns Canvas Object with qr code drawn on it
|
||||
/*
|
||||
* String text, optional Object options, Function callback
|
||||
*/
|
||||
var draw = exports.draw = function (text, options, cb) {
|
||||
var args = Array.prototype.slice.call(arguments)
|
||||
cb = args.pop()
|
||||
if (typeof cb !== 'function') {
|
||||
throw new TypeError('last argument must be a function')
|
||||
}
|
||||
|
||||
text = args.shift()
|
||||
options = args.shift() || {}
|
||||
options = parseOptions(options)
|
||||
|
||||
// NOTE the width and height are determined from within the qr code lib and are not configurable from the outside yet
|
||||
|
||||
var drawInstance = new QRCodeDraw()
|
||||
drawInstance.draw(new Canvas(200, 200), text, options, function (error, canvas, qrWidth) {
|
||||
cb(error, canvas, qrWidth)
|
||||
})
|
||||
}
|
||||
|
||||
// returns data uri for drawn qrcode png
|
||||
exports.toDataURL = exports.toDataURI = function (text, options, cb) {
|
||||
if (typeof options === 'function') {
|
||||
cb = options
|
||||
options = {}
|
||||
}
|
||||
|
||||
draw(text, options, function (error, canvas) {
|
||||
if (error) {
|
||||
cb(error)
|
||||
} else {
|
||||
canvas.toDataURL(cb)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// synchronous PNGStream
|
||||
exports.toPNGStream = function (text, WSpath, options, cb) {
|
||||
if (typeof options === 'function') {
|
||||
cb = options
|
||||
options = {}
|
||||
}
|
||||
|
||||
var out = fs.createWriteStream(WSpath)
|
||||
|
||||
draw(text, options, function (error, canvas) {
|
||||
var stream
|
||||
if (error) {
|
||||
cb(error, '')
|
||||
} else {
|
||||
stream = canvas.createPNGStream()
|
||||
}
|
||||
|
||||
stream.pipe(out)
|
||||
|
||||
stream.on('end', function () {
|
||||
cb(error, '')
|
||||
})
|
||||
|
||||
stream.pipe(out)
|
||||
})
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// returns bytes written to file
|
||||
exports.save = function (path, text, options, cb) {
|
||||
if (typeof options === 'function') {
|
||||
cb = options
|
||||
options = {}
|
||||
}
|
||||
|
||||
var fileExt = path.slice((path.lastIndexOf('.') - 1 >>> 0) + 2).toLowerCase()
|
||||
|
||||
if (fileExt === 'svg') {
|
||||
saveSvg(path, text, options, cb)
|
||||
} else {
|
||||
savePng(path, text, options, cb)
|
||||
}
|
||||
}
|
||||
|
||||
function savePng (path, text, options, cb) {
|
||||
draw(text, options, function (error, canvas) {
|
||||
if (error) {
|
||||
throw new Error(error)
|
||||
}
|
||||
|
||||
var fd
|
||||
var buf
|
||||
var fdAndBuf = function () {
|
||||
fs.write(fd, buf, 0, buf.length, 0, function (fsErr1, written) {
|
||||
fs.close(fd, function (fsErr2) {
|
||||
if (cb) cb(fsErr1 || fsErr2, written)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// run non dependent async calls at the same time ish
|
||||
canvas.toBuffer(function (canvasErr, _buf) {
|
||||
if (canvasErr) return cb(canvasErr)
|
||||
buf = _buf
|
||||
if (fd) fdAndBuf()
|
||||
})
|
||||
|
||||
fs.open(path, 'w', function (fsErr, _fd) {
|
||||
if (fsErr) return cb(fsErr)
|
||||
fd = _fd
|
||||
if (buf) fdAndBuf()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function saveSvg (path, text, options, cb) {
|
||||
exports.drawSvg(text, options, function (error, code) {
|
||||
if (!error) {
|
||||
fs.writeFile(path, code, function (fsErr) {
|
||||
return cb(fsErr, fsErr ? null : code)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//
|
||||
// this returns an array of points that have either a 0 or 1 value representing 0 for light and 1 for dark
|
||||
// these values include points in the white edge of the qrcode because that edge is actually part of the spec
|
||||
//
|
||||
exports.drawBitArray = function (text, options, cb) {
|
||||
if (typeof options === 'function') {
|
||||
cb = options
|
||||
options = {}
|
||||
}
|
||||
options = parseOptions(options)
|
||||
|
||||
var drawInstance = new QRCodeDraw()
|
||||
drawInstance.drawBitArray(text, options, function (error, bits, width) {
|
||||
cb(error, bits, width)
|
||||
})
|
||||
}
|
||||
|
||||
//
|
||||
// draw qr in your terminal!
|
||||
//
|
||||
exports.drawText = function (text, options, cb) {
|
||||
if (typeof options === 'function') {
|
||||
cb = options
|
||||
options = {}
|
||||
}
|
||||
|
||||
var drawInstance = new QRCodeDraw()
|
||||
drawInstance.drawBitArray(text, options, function (error, bits, width) {
|
||||
if (!error) {
|
||||
var code = terminalRender.renderBits(bits, width)
|
||||
cb(error, code)
|
||||
} else {
|
||||
cb(error, null)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
exports.drawSvg = function (text, options, cb) {
|
||||
if (typeof options === 'function') {
|
||||
cb = options
|
||||
options = {}
|
||||
}
|
||||
|
||||
var drawInstance = new QRCodeDraw()
|
||||
drawInstance.drawBitArray(text, options, function (error, bits, width) {
|
||||
if (!error) {
|
||||
var code = svgRender.renderBits(bits, width, options)
|
||||
cb(error, code)
|
||||
} else {
|
||||
cb(error, null)
|
||||
}
|
||||
})
|
||||
}
|
||||
module.exports = require('./server')
|
||||
|
|
|
@ -1,166 +0,0 @@
|
|||
/*
|
||||
* copyright 2010-2012 Ryan Day
|
||||
* http://github.com/soldair/node-qrcode
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* canvas example and fallback support example provided by Joshua Koo
|
||||
* http://jabtunes.com/labs/qrcode.html
|
||||
* "Instant QRCode Mashup by Joshua Koo!"
|
||||
* as far as i can tell the page and the code on the page are public domain
|
||||
*
|
||||
* original table example and library provided by Kazuhiko Arase
|
||||
* http://d-project.googlecode.com/svn/trunk/misc/qrcode/js/
|
||||
*
|
||||
*/
|
||||
|
||||
var QRCodeLib = require('../core/qrcode')
|
||||
var ErrorCorrectionLevel = require('../core/error-correction-level')
|
||||
|
||||
exports.QRCodeDraw = QRCodeDraw
|
||||
exports.QRErrorCorrectLevel = ErrorCorrectionLevel
|
||||
exports.QRCode = QRCodeLib
|
||||
|
||||
function QRCodeDraw () {}
|
||||
|
||||
QRCodeDraw.prototype = {
|
||||
scale: 4, // 4 px module size
|
||||
defaultMargin: 20,
|
||||
marginScaleFactor: 5,
|
||||
color: {
|
||||
dark: 'black',
|
||||
light: 'white'
|
||||
},
|
||||
QRErrorCorrectLevel: ErrorCorrectionLevel,
|
||||
|
||||
draw: function (canvas, text, options, cb) {
|
||||
var error
|
||||
|
||||
var args = Array.prototype.slice.call(arguments)
|
||||
cb = args.pop()
|
||||
canvas = args.shift()
|
||||
text = args.shift()
|
||||
options = args.shift() || {}
|
||||
|
||||
if (typeof cb !== 'function') {
|
||||
// enforce callback api just in case the processing can be made async in the future
|
||||
// or support proc open to libqrencode
|
||||
throw new Error('callback required')
|
||||
}
|
||||
|
||||
if (typeof options !== 'object') {
|
||||
options.errorCorrectionLevel = options
|
||||
}
|
||||
|
||||
this.scale = options.scale || this.scale
|
||||
this.margin = typeof (options.margin) === 'undefined' ? this.defaultMargin : options.margin
|
||||
|
||||
// create qrcode!
|
||||
try {
|
||||
var qr = new QRCodeLib(text, options)
|
||||
var scale = this.scale || 4
|
||||
var ctx = canvas.getContext('2d')
|
||||
var width = 0
|
||||
|
||||
var margin = this.marginWidth()
|
||||
var currenty = margin
|
||||
width = this.dataWidth(qr) + margin * 2
|
||||
|
||||
this.resetCanvas(canvas, ctx, width)
|
||||
|
||||
for (var r = 0, rl = qr.getModuleCount(); r < rl; r++) {
|
||||
var currentx = margin
|
||||
for (var c = 0, cl = qr.getModuleCount(); c < cl; c++) {
|
||||
if (qr.isDark(r, c)) {
|
||||
ctx.fillStyle = this.color.dark
|
||||
ctx.fillRect(currentx, currenty, scale, scale)
|
||||
} else if (this.color.light) {
|
||||
// if falsy configured color
|
||||
ctx.fillStyle = this.color.light
|
||||
ctx.fillRect(currentx, currenty, scale, scale)
|
||||
}
|
||||
currentx += scale
|
||||
}
|
||||
currenty += scale
|
||||
}
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
cb(error, canvas, width)
|
||||
},
|
||||
|
||||
drawBitArray: function (/* text, errorCorrectLevel,options,cb */) {
|
||||
var args = Array.prototype.slice.call(arguments)
|
||||
var cb = args.pop()
|
||||
var text = args.shift()
|
||||
var options = args.shift() || {}
|
||||
var error
|
||||
|
||||
// argument processing
|
||||
if (typeof cb !== 'function') {
|
||||
// enforce callback api just in case the processing can be made async in the future
|
||||
// or support proc open to libqrencode
|
||||
throw new Error('callback required as last argument')
|
||||
}
|
||||
|
||||
// create qrcode!
|
||||
try {
|
||||
var qr = new QRCodeLib(text, options)
|
||||
var width = 0
|
||||
var bits
|
||||
var bitc = 0
|
||||
|
||||
width = this.dataWidth(qr, 1)
|
||||
bits = new Array(width * width)
|
||||
|
||||
for (var r = 0, rl = qr.getModuleCount(); r < rl; r++) {
|
||||
for (var c = 0, cl = qr.getModuleCount(); c < cl; c++) {
|
||||
if (qr.isDark(r, c)) {
|
||||
bits[bitc] = 1
|
||||
} else {
|
||||
bits[bitc] = 0
|
||||
}
|
||||
bitc++
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
error = e
|
||||
console.log(e.stack)
|
||||
}
|
||||
|
||||
cb(error, bits, width)
|
||||
},
|
||||
|
||||
marginWidth: function () {
|
||||
var margin = this.margin
|
||||
this.scale = this.scale || 4
|
||||
// elegant white space next to code is required by spec
|
||||
if ((this.scale * this.marginScaleFactor > margin) && margin > 0) {
|
||||
margin = this.scale * this.marginScaleFactor
|
||||
}
|
||||
return margin
|
||||
},
|
||||
|
||||
dataWidth: function (qr, scale) {
|
||||
return qr.getModuleCount() * (scale || this.scale || 4)
|
||||
},
|
||||
|
||||
resetCanvas: function (canvas, ctx, width) {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
||||
if (!canvas.style) canvas.style = {}
|
||||
canvas.style.height = canvas.height = width// square!
|
||||
canvas.style.width = canvas.width = width
|
||||
|
||||
if (this.color.light) {
|
||||
ctx.fillStyle = this.color.light
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height)
|
||||
} else {
|
||||
// support transparent backgrounds?
|
||||
// not exactly to spec but i really would like someone to be able to add a background with heavily reduced luminosity for simple branding
|
||||
// i could just ditch this because you could also just set #******00 as the color =P
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
||||
}
|
||||
}
|
||||
}
|
111
lib/server.js
Normal file
111
lib/server.js
Normal file
|
@ -0,0 +1,111 @@
|
|||
var QRCode = require('./core/qrcode')
|
||||
var PngRenderer = require('./renderer/png')
|
||||
var Utf8Renderer = require('./renderer/utf8')
|
||||
var TerminalRenderer = require('./renderer/terminal')
|
||||
var SvgRenderer = require('./renderer/svg')
|
||||
|
||||
function checkParams (text, opts, cb) {
|
||||
if (typeof text === 'undefined') {
|
||||
throw new Error('String required as first argument')
|
||||
}
|
||||
|
||||
if (typeof cb === 'undefined') {
|
||||
cb = opts
|
||||
opts = {}
|
||||
}
|
||||
|
||||
if (typeof cb !== 'function') {
|
||||
throw new Error('Callback required as last argument')
|
||||
}
|
||||
|
||||
return {
|
||||
opts: opts,
|
||||
cb: cb
|
||||
}
|
||||
}
|
||||
|
||||
function getTypeFromFilename (path) {
|
||||
return path.slice((path.lastIndexOf('.') - 1 >>> 0) + 2).toLowerCase()
|
||||
}
|
||||
|
||||
function getRendererFromType (type) {
|
||||
switch (type) {
|
||||
case 'svg':
|
||||
return SvgRenderer
|
||||
|
||||
case 'txt':
|
||||
case 'utf8':
|
||||
return Utf8Renderer
|
||||
|
||||
case 'png':
|
||||
case 'image/png':
|
||||
default:
|
||||
return PngRenderer
|
||||
}
|
||||
}
|
||||
|
||||
function getStringRendererFromType (type) {
|
||||
switch (type) {
|
||||
case 'svg':
|
||||
return SvgRenderer
|
||||
|
||||
case 'terminal':
|
||||
return TerminalRenderer
|
||||
|
||||
case 'utf8':
|
||||
default:
|
||||
return Utf8Renderer
|
||||
}
|
||||
}
|
||||
|
||||
function render (renderFunc, text, params) {
|
||||
try {
|
||||
var data = QRCode.create(text, params.opts)
|
||||
return params.cb(null, renderFunc(data, params.opts))
|
||||
} catch (e) {
|
||||
return params.cb(e)
|
||||
}
|
||||
}
|
||||
|
||||
exports.create = QRCode.create
|
||||
|
||||
exports.toCanvas = require('./browser').toCanvas
|
||||
|
||||
exports.toString = function toString (text, opts, cb) {
|
||||
var params = checkParams(text, opts, cb)
|
||||
var renderer = getStringRendererFromType(params.opts.type)
|
||||
return render(renderer.render, text, params)
|
||||
}
|
||||
|
||||
exports.toDataURL = function toDataURL (text, opts, cb) {
|
||||
var params = checkParams(text, opts, cb)
|
||||
var renderer = getRendererFromType(params.opts.type)
|
||||
|
||||
return render(renderer.renderToDataURL, text, params)
|
||||
}
|
||||
|
||||
exports.toFile = function toFile (path, text, opts, cb) {
|
||||
if (arguments.length < 3) {
|
||||
throw new Error('Too few arguments provided')
|
||||
}
|
||||
|
||||
var params = checkParams(text, opts, cb)
|
||||
var type = params.opts.type || getTypeFromFilename(path)
|
||||
var renderer = getRendererFromType(type)
|
||||
var renderToFile = renderer.renderToFile.bind(null, path)
|
||||
|
||||
return render(renderToFile, text, params)
|
||||
}
|
||||
|
||||
exports.toFileStream = function toFileStream (path, text, opts, cb) {
|
||||
if (arguments.length < 3) {
|
||||
throw new Error('Too few arguments provided')
|
||||
}
|
||||
|
||||
var params = checkParams(text, opts, cb)
|
||||
var type = params.opts.type || getTypeFromFilename(path)
|
||||
var renderer = getRendererFromType(type)
|
||||
var renderToFileStream = renderer.renderToFileStream.bind(null, path)
|
||||
|
||||
return render(renderToFileStream, text, params)
|
||||
}
|
Loading…
Reference in a new issue