Skip to content

Commit

Permalink
feat(javascript): enable use with NPM
Browse files Browse the repository at this point in the history
  • Loading branch information
gfortaine committed Dec 29, 2022
1 parent 0dbd3b2 commit 5b3f8df
Show file tree
Hide file tree
Showing 16 changed files with 213 additions and 70 deletions.
7 changes: 7 additions & 0 deletions typescript-javascript/.gitignore
@@ -0,0 +1,7 @@
# Dependency directories
node_modules/

# build artifacts
dist
dist-*
types
5 changes: 4 additions & 1 deletion typescript-javascript/Readme.markdown
Expand Up @@ -36,12 +36,15 @@ Examples
--------

```typescript
import qrcodegen from "qr-code-generator";
import { toSvgString } from "qr-code-generator/utils";

// Name abbreviated for the sake of these examples here
const QRC = qrcodegen.QrCode;

// Simple operation
const qr0 = QRC.encodeText("Hello, world!", QRC.Ecc.MEDIUM);
const svg = toSvgString(qr0, 4); // See qrcodegen-input-demo
const svg = toSvgString(qr0, 4, "#FFFFFF", "#000000"); // See qrcodegen-input-demo

// Manual operation
const segs = qrcodegen.QrSegment.makeSegments("3141592653589793238462643383");
Expand Down
3 changes: 1 addition & 2 deletions typescript-javascript/build.sh
100644 → 100755
Expand Up @@ -21,5 +21,4 @@
# Software.
#

tsc --strict --lib DOM,DOM.Iterable,ES6 --target ES6 qrcodegen.ts qrcodegen-input-demo.ts
tsc --strict --lib DOM,DOM.Iterable,ES6 --target ES6 qrcodegen.ts qrcodegen-output-demo.ts
./node_modules/.bin/tsc --strict --lib DOM,DOM.Iterable,ES6 --target ES6 *.ts utils/index.ts --outDir dist-demo
3 changes: 3 additions & 0 deletions typescript-javascript/index.cjs
@@ -0,0 +1,3 @@
const qrcodegen = require("./dist/qrcodegen.cjs").default;

module.exports = qrcodegen;
3 changes: 3 additions & 0 deletions typescript-javascript/index.js
@@ -0,0 +1,3 @@
import qrcodegen from "./dist-esm/qrcodegen.js";

export default qrcodegen;
40 changes: 40 additions & 0 deletions typescript-javascript/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

67 changes: 67 additions & 0 deletions typescript-javascript/package.json
@@ -0,0 +1,67 @@
{
"name": "qr-code-generator",
"version": "1.8.1",
"description": "QR Code generator library in multiple languages",
"type": "module",
"exports": {
".": {
"types": "./types/qrcodegen.d.ts",
"require": "./index.cjs",
"default": "./index.js"
},
"./package.json": "./package.json",
"./utils": {
"types": "./types/utils/index.d.ts",
"require": "./dist/utils/index.cjs",
"default": "./dist-esm/utils/index.js"
}
},
"typesVersions": {
"*": {
"utils": [
"types/utils/index.d.ts"
]
}
},
"types": "types/qrcodegen.d.ts",
"files": [
"index.cjs",
"index.js",
"dist",
"dist-esm",
"types"
],
"engines": {
"node": ">=14.16"
},
"scripts": {
"build:es5": "tsc -p ./tsconfig.es5.json",
"postbuild:es5": "find ./dist -name \"*.js\" -exec sh -c 'mv \"$1\" \"${1%.js}.cjs\"' _ {} \\;",
"build:es6": "tsc -p ./tsconfig.es6.json",
"prebuild": "npm run clean",
"build": "npm run build:es5 & npm run build:es6",
"clean": "rm -rf dist dist-* types",
"predemo": "./build.sh",
"demo": "npx --yes browser-sync start --server --index qrcodegen-$npm_config_type-demo.html --no-notify --no-open --no-snippet --no-ui --no-ghost-mode",
"prepublishOnly": "npm run build"
},
"devDependencies": {
"typescript": "^4.9.4"
},
"repository": {
"type": "git",
"url": "git+https://github.com/nayuki/QR-Code-generator.git"
},
"keywords": [
"qr",
"qrcode",
"generator",
"svg"
],
"author": "Project Nayuki (me@nayuki.io)",
"license": "MIT",
"bugs": {
"url": "https://github.com/nayuki/QR-Code-generator/issues"
},
"homepage": "https://github.com/nayuki/QR-Code-generator#readme"
}
4 changes: 2 additions & 2 deletions typescript-javascript/qrcodegen-input-demo.html
Expand Up @@ -147,8 +147,8 @@ <h1>QR Code generator input demo (JavaScript)</h1>
</tbody>
</table>
</form>
<script type="application/javascript" src="qrcodegen.js"></script>
<script type="application/javascript" src="qrcodegen-input-demo.js"></script>
<script type="module" src="dist-demo/qrcodegen.js"></script>
<script type="module" src="dist-demo/qrcodegen-input-demo.js"></script>

<hr>
<p>Copyright © Project Nayuki – <a href="https://www.nayuki.io/page/qr-code-generator-library">https://www.nayuki.io/page/qr-code-generator-library</a></p>
Expand Down
45 changes: 2 additions & 43 deletions typescript-javascript/qrcodegen-input-demo.ts
Expand Up @@ -23,6 +23,8 @@

"use strict";

import qrcodegen from "./qrcodegen.js";
import { drawCanvas, toSvgString } from "./utils/index.js";

namespace app {

Expand Down Expand Up @@ -145,49 +147,6 @@ namespace app {
`data bits = ${qrcodegen.QrSegment.getTotalBits(segs, qr.version) as number}.`;
}


// Draws the given QR Code, with the given module scale and border modules, onto the given HTML
// canvas element. The canvas's width and height is resized to (qr.size + border * 2) * scale.
// The drawn image is purely dark and light, and fully opaque.
// The scale must be a positive integer and the border must be a non-negative integer.
function drawCanvas(qr: qrcodegen.QrCode, scale: number, border: number, lightColor: string, darkColor: string, canvas: HTMLCanvasElement): void {
if (scale <= 0 || border < 0)
throw new RangeError("Value out of range");
const width: number = (qr.size + border * 2) * scale;
canvas.width = width;
canvas.height = width;
let ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
for (let y = -border; y < qr.size + border; y++) {
for (let x = -border; x < qr.size + border; x++) {
ctx.fillStyle = qr.getModule(x, y) ? darkColor : lightColor;
ctx.fillRect((x + border) * scale, (y + border) * scale, scale, scale);
}
}
}


// Returns a string of SVG code for an image depicting the given QR Code, with the given number
// of border modules. The string always uses Unix newlines (\n), regardless of the platform.
function toSvgString(qr: qrcodegen.QrCode, border: number, lightColor: string, darkColor: string): string {
if (border < 0)
throw new RangeError("Border must be non-negative");
let parts: Array<string> = [];
for (let y = 0; y < qr.size; y++) {
for (let x = 0; x < qr.size; x++) {
if (qr.getModule(x, y))
parts.push(`M${x + border},${y + border}h1v1h-1z`);
}
}
return `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 ${qr.size + border * 2} ${qr.size + border * 2}" stroke="none">
<rect width="100%" height="100%" fill="${lightColor}"/>
<path d="${parts.join(" ")}" fill="${darkColor}"/>
</svg>
`
}


export function handleVersionMinMax(which: "min"|"max"): void {
const minElem: HTMLInputElement = getInput("version-min-input");
const maxElem: HTMLInputElement = getInput("version-max-input");
Expand Down
4 changes: 2 additions & 2 deletions typescript-javascript/qrcodegen-output-demo.html
Expand Up @@ -57,8 +57,8 @@ <h1>QR Code generator output demo (JavaScript)</h1>
<p>(Are the JavaScript files missing?)</p>
<p>(The JavaScript code needs to be compiled from the TypeScript code.)</p>
</div>
<script type="application/javascript" src="qrcodegen.js"></script>
<script type="application/javascript" src="qrcodegen-output-demo.js"></script>
<script type="module" src="dist-demo/qrcodegen.js"></script>
<script type="module" src="dist-demo/qrcodegen-output-demo.js"></script>
<hr>
<p>Copyright © Project Nayuki – <a href="https://www.nayuki.io/page/qr-code-generator-library">https://www.nayuki.io/page/qr-code-generator-library</a></p>
</body>
Expand Down
22 changes: 2 additions & 20 deletions typescript-javascript/qrcodegen-output-demo.ts
Expand Up @@ -23,6 +23,8 @@

"use strict";

import qrcodegen from "./qrcodegen.js";
import { drawCanvas } from "./utils/index.js";

namespace app {

Expand Down Expand Up @@ -200,26 +202,6 @@ namespace app {
}


// Draws the given QR Code, with the given module scale and border modules, onto the given HTML
// canvas element. The canvas's width and height is resized to (qr.size + border * 2) * scale.
// The drawn image is purely dark and light, and fully opaque.
// The scale must be a positive integer and the border must be a non-negative integer.
function drawCanvas(qr: qrcodegen.QrCode, scale: number, border: number, lightColor: string, darkColor: string, canvas: HTMLCanvasElement): void {
if (scale <= 0 || border < 0)
throw new RangeError("Value out of range");
const width: number = (qr.size + border * 2) * scale;
canvas.width = width;
canvas.height = width;
let ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
for (let y = -border; y < qr.size + border; y++) {
for (let x = -border; x < qr.size + border; x++) {
ctx.fillStyle = qr.getModule(x, y) ? darkColor : lightColor;
ctx.fillRect((x + border) * scale, (y + border) * scale, scale, scale);
}
}
}


function toUtf8ByteArray(str: string): Array<number> {
str = encodeURI(str);
let result: Array<number> = [];
Expand Down
3 changes: 3 additions & 0 deletions typescript-javascript/qrcodegen.ts
Expand Up @@ -989,3 +989,6 @@ namespace qrcodegen.QrSegment {

}
}

// https://github.com/nayuki/QR-Code-generator/issues/10#issuecomment-831582482
export default qrcodegen;
8 changes: 8 additions & 0 deletions typescript-javascript/tsconfig.base.json
@@ -0,0 +1,8 @@
{
"compilerOptions": {
"strict": true,
"declaration": true,
"declarationDir": "./types"
},
"include": ["qrcodegen.ts", "utils/index.ts"]
}
7 changes: 7 additions & 0 deletions typescript-javascript/tsconfig.es5.json
@@ -0,0 +1,7 @@
{
"extends": "./tsconfig.base",
"compilerOptions": {
"target": "ES5",
"outDir": "dist"
}
}
7 changes: 7 additions & 0 deletions typescript-javascript/tsconfig.es6.json
@@ -0,0 +1,7 @@
{
"extends": "./tsconfig.base",
"compilerOptions": {
"target": "ES2015",
"outDir": "dist-esm"
}
}
55 changes: 55 additions & 0 deletions typescript-javascript/utils/index.ts
@@ -0,0 +1,55 @@
import qrcodegen from "../qrcodegen";

// Draws the given QR Code, with the given module scale and border modules, onto the given HTML
// canvas element. The canvas's width and height is resized to (qr.size + border * 2) * scale.
// The drawn image is purely dark and light, and fully opaque.
// The scale must be a positive integer and the border must be a non-negative integer.
export function drawCanvas(
qr: qrcodegen.QrCode,
scale: number,
border: number,
lightColor: string,
darkColor: string,
canvas: HTMLCanvasElement
): void {
if (scale <= 0 || border < 0) throw new RangeError("Value out of range");

const width: number = (qr.size + border * 2) * scale;
canvas.width = width;
canvas.height = width;
let ctx = canvas.getContext("2d") as CanvasRenderingContext2D;

for (let y = -border; y < qr.size + border; y++) {
for (let x = -border; x < qr.size + border; x++) {
ctx.fillStyle = qr.getModule(x, y) ? darkColor : lightColor;
ctx.fillRect((x + border) * scale, (y + border) * scale, scale, scale);
}
}
}

// Returns a string of SVG code for an image depicting the given QR Code, with the given number
// of border modules. The string always uses Unix newlines (\n), regardless of the platform.
export function toSvgString(
qr: qrcodegen.QrCode,
border: number,
lightColor: string,
darkColor: string
): string {
if (border < 0) throw new RangeError("Border must be non-negative");
let parts: Array<string> = [];
for (let y = 0; y < qr.size; y++) {
for (let x = 0; x < qr.size; x++) {
if (qr.getModule(x, y))
parts.push(`M${x + border},${y + border}h1v1h-1z`);
}
}
return `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 ${
qr.size + border * 2
} ${qr.size + border * 2}" stroke="none">
<rect width="100%" height="100%" fill="${lightColor}"/>
<path d="${parts.join(" ")}" fill="${darkColor}"/>
</svg>
`;
}

0 comments on commit 5b3f8df

Please sign in to comment.