Skip to content
This repository was archived by the owner on Feb 2, 2021. It is now read-only.

Use qr-image for qr code generation #956

Merged
merged 1 commit into from
May 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"progress-stream": "0.5.0",
"properties-parser": "0.2.3",
"pullstream": "https://github.com/icenium/node-pullstream/tarball/master",
"qr-image": "3.2.0",
"qrcode-generator": "1.0.0",
"request": "2.81.0",
"rimraf": "2.2.6",
Expand All @@ -74,6 +75,7 @@
"@types/chai": "3.4.34",
"@types/chai-as-promised": "0.0.29",
"@types/node": "6.0.61",
"@types/qr-image": "3.2.0",
"@types/request": "0.0.42",
"@types/semver": "5.3.30",
"@types/source-map": "0.5.0",
Expand Down
58 changes: 11 additions & 47 deletions services/qr.ts
Original file line number Diff line number Diff line change
@@ -1,56 +1,20 @@
let qrcode = require("qrcode-generator");
import { imageSync } from "qr-image";
import { escape } from "querystring";

export class QrCodeGenerator implements IQrCodeGenerator {
// The order is important.
private static ERROR_CORRECTION_LEVEL = ["L", "M", "Q", "H"];

// https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders/Additional_information
private static MAX_BLOCK_VERSION = 40;

constructor(private $staticConfig: Config.IStaticConfig) { }

public async generateQrCode(data: string): Promise<any> {
let errorCorrectionLevel = "L";
let errorCorrectionOffset = _.indexOf(QrCodeGenerator.ERROR_CORRECTION_LEVEL, errorCorrectionLevel);

// 4 is from the qrcode-generator source code.
let maxReedSolomonBlockIndex = QrCodeGenerator.MAX_BLOCK_VERSION / 4 - errorCorrectionOffset;

for (let i = 1; i <= maxReedSolomonBlockIndex; ++i) {
let qr = qrcode(i, errorCorrectionLevel);
try {
qr.addData(data);
qr.make();
} catch (ex) {
let expected = "code length overflow.";
if (ex.message && ex.message.substr(0, expected.length) === expected) {
continue;
} else {
throw ex;
}
}

return qr;
}

// Since the max Reed-Solomon block index was calculated before the for loop and no exception was thrown in it here the only error can be because of long project name.
// Return null and expect the consumer to take caution in handling this case
return null;
}
constructor(private $staticConfig: Config.IStaticConfig,
private $logger: ILogger) { }

public async generateDataUri(data: string): Promise<string> {
let qr = await this.generateQrCode(data);
let dataUri: string = null;
if (qr) {
let cells = qr.getModuleCount();
let size = this.$staticConfig.QR_SIZE;
let cellSize = Math.ceil(size / (cells + 2 * 4 /* margin */));

let imgTag = qr.createImgTag(cellSize);
dataUri = imgTag.split('src="')[1].split('"')[0];
let result: string = null;
try {
const qrSvg = imageSync(data, { size: this.$staticConfig.QR_SIZE, type: "svg" }).toString();
result = `data:image/svg+xml;utf-8,${escape(qrSvg)}`;
} catch (err) {
this.$logger.trace(`Failed to generate QR code for ${data}`, err);
}

return dataUri;
return result;
}
}

Expand Down
2 changes: 1 addition & 1 deletion static-config-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class StaticConfigBase implements Config.IStaticConfig {
public ERROR_REPORT_SETTING_NAME: string = null;
public APP_RESOURCES_DIR_NAME = "App_Resources";
public COMMAND_HELP_FILE_NAME = 'command-help.json';
public QR_SIZE = 300;
public QR_SIZE = 5;
public RESOURCE_DIR_PATH = __dirname;
public SYS_REQUIREMENTS_LINK: string;
public HTML_CLI_HELPERS_DIR: string;
Expand Down