bwip-js
Version:
JavaScript barcode generator supporting over 100 types and standards.
305 lines (297 loc) • 13.3 kB
JavaScript
var fs = require('fs');
var bwipjs = require('..');
var symdesc = require('../lib/symdesc');
function usage(exit) {
console.log(
"Usage: bwip-js symbol-name text [options...] file.{png,svg}\n" +
" bwip-js --bcid=symbol-name --text=text [options...] file.{png,svg}\n" +
"\n" +
"Examples:\n" +
" bwip-js code128 012345678 includetext textcolor=ff0000 my-code128.png\n" +
" bwip-js qrcode 'https://bwip-js.metafloor.com' qrcode.svg\n" +
"\n" +
"'bwip-js --help' for more information.\n" +
"'bwip-js --symbols' for a list of supported barcode symbols.\n" +
"'bwip-js --version' for version information.\n" +
"");
if (exit) {
process.exit(1);
}
}
function help() {
usage();
for (var i = 0; i < optlist.length; i++) {
console.log(' --' + optlist[i].name)
console.log(indent(optlist[i].desc));
}
console.log(
"\nThe double-dashes '--' are not required before each option.\n" +
"For example, you can specify '--includetext' or 'includetext'.");
}
// Indent the text 8 spaces
function indent(text) {
return text.replace(/^/, ' ').replace(/\n/g, '\n ');
}
// spec is one of: "font-name,y-mult,x-mult,path-to-font-file"
// "font-name,size-mult,path-to-font-file"
// "font-name,path-to-font-file"
function loadfont(spec) {
var vals = spec.split(',');
try {
if (vals.length == 4) {
bwipjs.loadFont(vals[0], +vals[1], +vals[2], fs.readFileSync(vals[3]));
} else if (vals.length == 3) {
bwipjs.loadFont(vals[0], +vals[1], fs.readFileSync(vals[2]));
} else if (vals.length == 2) {
bwipjs.loadFont(vals[0], fs.readFileSync(vals[1]));
} else {
console.log("Invalid --loadfont format.");
console.log("Try 'bwip-js --help' for more information.");
process.exit(1);
}
} catch(e) {
console.log('bwip-js: ' + e);
process.exit(1);
}
}
var optlist = [
{ name: 'help', type: 'boolean',
desc: 'Displays this help message.' },
{ name: 'version', type: 'boolean',
desc: 'Displays the bwip-js and BWIPP version strings.' },
{ name: 'symbols', type: 'boolean',
desc: 'Display a list of the supported barcode types.' },
{ name: 'loadfont', type: 'string',
desc: 'Loads a truetype/opentype font. Format of this option is one of:\n\n' +
' --loadfont=font-name,y-mult,x-mult,path-to-font-file\n' +
' --loadfont=font-name,size-mult,path-to-font-file\n' +
' --loadfont=font-name,path-to-font-file\n\n' +
'For example: --loadfont=Courier,100,120,c:\\windows\\fonts\\cour.ttf' },
// bwipjs options
{ name: 'bcid', type: 'string',
desc: 'Barcode symbol name/type. Required.' },
{ name: 'text', type: 'string',
desc: 'The text to encode. Required.\n' +
'Use single quotes around the text to protect from the shell.' },
{ name: 'scaleX', type: 'int',
desc: 'The x-axis scaling factor. Must be an integer > 0. Default is 2.' },
{ name: 'scaleY', type: 'int',
desc: 'The y-axis scaling factor. Must be an integer > 0. Default is scaleX.' },
{ name: 'scale', type: 'int',
desc: 'Sets both the x-axis and y-axis scaling factors. Must be an integer > 0.' },
{ name: 'rotate', type: 'string',
desc: 'Rotates the image to one of the four orthogonal orientations.\n' +
'A string value. Must be one of:\n' +
' N : Normal orientation.\n' +
' R : Rotated right 90 degrees.\n' +
' L : Rotated left 90 degrees.\n' +
' I : Inverted, rotated 180 degrees.' },
{ name: 'padding', type: 'int',
desc: 'Shorthand for setting paddingtop, paddingleft, paddingright, and paddingbottom.' },
{ name: 'paddingwidth', type: 'int',
desc: 'Shorthand for setting paddingleft and paddingright.' },
{ name: 'paddingheight', type: 'int',
desc: 'Shorthand for setting paddingtop and paddingbottom.' },
{ name: 'paddingtop', type: 'int',
desc: 'Sets the height of the padding area, in points, on the top of\n' +
'the barcode image. Rotates and scales with the image.' },
{ name: 'paddingleft', type: 'int',
desc: 'Sets the width of the padding area, in points, on the left side\n' +
'of the barcode image. Rotates and scales with the image.' },
{ name: 'paddingright', type: 'int',
desc: 'Sets the width of the padding area, in points, on the right side\n' +
'of the barcode image. Rotates and scales with the image.' },
{ name: 'paddingbottom', type: 'int',
desc: 'Sets the height of the padding area, in points, on the bottom of\n' +
'the barcode image. Rotates and scales with the image.' },
// { name: 'monochrome', type: 'boolean',
// desc: 'Sets the human-readable text to render in monochrome.\n'
// 'Default is false which renders 256-level gray-scale anti-aliased text.' },
// bwipp options
{ name: 'alttext', type: 'string',
desc: 'The human-readable text to use instead of the encoded text.' },
{ name: 'includecheck', type: 'boolean',
desc: 'Generate check digit(s) for symbologies where the use of check digits is\n' +
'optional.' },
{ name: 'includecheckintext', type: 'boolean',
desc: 'Show the calculated check digit in the human readable text.' },
{ name: 'parse', type: 'boolean',
desc: 'In supporting barcode symbologies, when the parse option is specified,\n' +
'any instances of ^NNN in the data field are replaced with their equivalent\n' +
'ASCII value, useful for specifying unprintable characters.' },
{ name: 'parsefnc', type: 'boolean',
desc: 'In supporting barcode symbologies, when the parsefnc option is specified,\n' +
'non-data function characters can be specified by escaped combinations such\n' +
'as ^FNC1, ^FNC4 and ^SFT.' },
{ name: 'height', type: 'float',
desc: 'Height of longest bar, in millimeters.' },
{ name: 'width', type: 'float',
desc: 'Stretch the symbol to approximately this width, in millimeters.\n' +
'Not recommended unless scale is at least 5.' },
{ name: 'inkspread', type: 'float',
desc: 'Amount by which to reduce the bar widths to compensate for inkspread,\n' +
'in points. Not recommended unless scale is at least 5.' },
{ name: 'inkspreadh', type: 'float',
desc: 'For matrix barcodes, the amount by which to reduce the width of dark\n' +
'modules to compensate for inkspread, in points.\n' +
'Not recommended unless scale is at least 5.\n\n' +
'Note: inkspreadh is most useful for stacked-linear type barcodes such as\n' +
'PDF417 and Codablock F.' },
{ name: 'inkspreadv', type: 'float',
desc: 'For matrix barcodes, the amount by which to reduce the height of dark\n' +
'modules to compensate for inkspread, in points.\n' +
'Not recommended unless scale is at least 5.' },
{ name: 'dotty', type: 'boolean',
desc: 'For matrix barcodes, render the modules as dots rather than squares.\n' +
'The dot radius can be adjusted using the inkspread option.' },
{ name: 'includetext', type: 'boolean',
desc: 'Show human readable text for data in symbol.' },
{ name: 'textfont', type: 'string',
desc: 'The font name to use for the text.' },
{ name: 'textsize', type: 'int',
desc: 'The font size of the text, in points.' },
{ name: 'textgaps', type: 'int',
desc: 'The inter-character spacing of the text.' },
{ name: 'textxalign', type: 'string',
desc: 'Specifies where to horizontally position the text.' },
{ name: 'textyalign', type: 'string',
desc: 'Specifies where to vertically position the text.' },
{ name: 'textxoffset', type: 'int',
desc: 'The horizontal position of the text, in points, relative to the\n' +
'default position.' },
{ name: 'textyoffset', type: 'int',
desc: 'The vertical position of the text, in points, relative to the\n' +
'default position.' },
{ name: 'showborder', type: 'boolean',
desc: 'Display a border around the symbol.' },
{ name: 'borderwidth', type: 'int',
desc: 'Width of a border, in points.' },
{ name: 'borderleft', type: 'int',
desc: 'Left margin gap of the border, in points.' },
{ name: 'borderright', type: 'int',
desc: 'Right margin gap of the border, in points.' },
{ name: 'bordertop', type: 'int',
desc: 'Top margin gap of the border, in points.' },
{ name: 'borderbottom', type: 'int',
desc: 'Bottom margin gap of the border, in points.' },
{ name: 'barcolor', type: 'string',
desc: 'Color of the bars, either as a hex RGB or RRGGBB value or a hex CCMMYYKK value.' },
{ name: 'backgroundcolor', type: 'string',
desc: 'Color of the image background, either as a hex RGB or RRGGBB value or a\n' +
'hex CCMMYYKK value. The default is a transparent background.' },
{ name: 'bordercolor', type: 'string',
desc: 'Color of the border, either as a hex RGB or RRGGBB value or a hex CCMMYYKK value.\n' +
'You must specify --showborder for this setting to take effect.' },
{ name: 'textcolor', type: 'string',
desc: 'Color of the text, either as a hex RGB or RRGGBB value or a hex CCMMYYKK value.' },
/*
{ name: 'addontextfont', type: 'string',
desc: 'The font name to use for the add-on text in ISBN, ISMN, and ISSN barcodes.' },
{ name: 'addontextsize', type: 'int',
desc: 'The font size of the add on text, in points.' },
{ name: 'addontextxoffset', type: 'int',
desc: 'Overrides the default positioning for the add on text.' },
{ name: 'addontextyoffset', type: 'int',
desc: 'Overrides the default positioning for the add on text.' },
*/
{ name: 'guardwhitespace', type: 'boolean',
desc: 'Display white space guards.' },
{ name: 'guardwidth', type: 'int',
desc: 'Width of white space guards, in points.' },
{ name: 'guardheight', type: 'int',
desc: 'Height of white space guards, in points.' },
{ name: 'guardleftpos', type: 'int',
desc: 'Amount of white space to guard to left of the symbol, in points.' },
{ name: 'guardrightpos', type: 'int',
desc: 'Amount of white space to guard to right of the symbol, in points.' },
{ name: 'guardleftypos', type: 'int',
desc: 'Vertical position of the guard symbols on the left, in points.' },
{ name: 'guardrightypos', type: 'int',
desc: 'Vertical position of the guard symbols on the right, in points.' },
];
var optmap = optlist.reduce(function(map, elt) { map[elt.name] = elt; return map; }, {});
var opts = {};
var argv = process.argv;
var outfile;
if (argv.length == 2) {
usage(true);
}
if (argv.length > 2 && !/^(--|bcid=)/.test(argv[2])) {
argv[2] = 'bcid=' + argv[2];
}
if (argv.length > 3 && !/^(--|text=)/.test(argv[3])) {
argv[3] = 'text=' + argv[3];
}
if (argv.length > 4 && !/^(--|\w+=)/.test(argv[argv.length-1])) {
outfile = argv.pop();
if (!/\.(png|svg)$/.test(outfile)) {
console.log(outfile + ": last argument must be a png or svg file name");
usage(true);
}
}
for (var i = 2, l = argv.length; i < l; i++) {
var a = argv[i];
if (/^--/.test(a)) {
a = a.substr(2);
}
var eq = a.indexOf('=');
if (eq > 0) {
var name = a.substr(0, eq);
var val = a.substr(eq+1);
if (name == 'loadfont') {
loadfont(val);
} else {
opts[name] = val;
}
} else if (optmap[a]) {
if (optmap[a].type != 'boolean') {
console.log('--' + a + ' : A value is expected.');
help();
process.exit(1);
}
opts[a] = true;
} else {
opts[a] = true;
}
}
if (opts.help) {
help();
} else if (opts.symbols) {
var arr = [];
for (var sym in symdesc) {
arr.push(sym + ' : ' + symdesc[sym].desc);
}
arr.sort();
for (var i = 0; i < arr.length; i++) {
console.log(' ' + arr[i]);
}
} else if (opts.version && !opts.bcid) {
console.log('bwip-js: ' + bwipjs.BWIPJS_VERSION + '\nBWIPP: ' + bwipjs.BWIPP_VERSION);
} else {
if (!opts.bcid) {
console.log('bwip-js: missing bcid');
usage(true);
} else if (!opts.text) {
console.log('bwip-js: missing text');
usage(true);
} else if (!outfile) {
console.log('bwip-js: missing outfile');
usage(true);
} else if (outfile.slice(-3) == 'png') {
bwipjs.toBuffer(opts, function (err, png) {
if (err) {
console.error(''+err);
process.exit(1);
}
try {
fs.writeFileSync(outfile, png);
} catch (e) {
console.log('bwip-js: ' + e);
}
});
} else {
fs.writeFileSync(outfile, bwipjs.toSVG(opts));
}
}
;