Skip to content

Commit

Permalink
breaking: next version (wip)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sec-ant committed Dec 15, 2024
1 parent e239c5f commit f5cdf80
Show file tree
Hide file tree
Showing 5,142 changed files with 16,301 additions and 11,122 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
2 changes: 1 addition & 1 deletion .github/workflows/preview-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- name: Checkout Repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: true
submodules: recursive

- name: Setup
uses: ./.github/actions/setup
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Checkout Repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: true
submodules: recursive

- name: Setup
uses: ./.github/actions/setup
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- name: Checkout Repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: true
submodules: recursive

- name: Setup
uses: ./.github/actions/setup
Expand Down
122 changes: 53 additions & 69 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@

[![npm](https://img.shields.io/npm/v/zxing-wasm)](https://www.npmjs.com/package/zxing-wasm/v/latest) [![npm bundle size (scoped)](https://img.shields.io/bundlephobia/minzip/zxing-wasm)](https://www.npmjs.com/package/zxing-wasm/v/latest) [![jsDelivr hits](https://img.shields.io/jsdelivr/npm/hm/zxing-wasm?color=%23ff5627)](https://cdn.jsdelivr.net/npm/zxing-wasm@latest/) [![deploy status](https://github.com/Sec-ant/zxing-wasm/actions/workflows/deploy.yml/badge.svg)](https://github.com/Sec-ant/zxing-wasm/actions/workflows/deploy.yml)

[ZXing-C++](https://github.com/zxing-cpp/zxing-cpp) WebAssembly as an ES/CJS module with types. Read or write barcodes in various JS runtimes: web, node, bun and deno.
[ZXing-C++](https://github.com/zxing-cpp/zxing-cpp) WebAssembly as an ES/CJS module with types. Read or write barcodes in various JS runtimes: Web, Node, Bun, and Deno.

Visit [this online demo](https://zxing-wasm-demo.deno.dev/) to quickly explore its basic functions. It works best on the latest chromium browsers.
<!-- Visit [this online demo](https://zxing-wasm-demo.deno.dev/) to quickly explore its basic functions. It works best on the latest Chromium browsers. -->

## Build

```bash
git clone --recurse-submodules https://github.com/Sec-ant/zxing-wasm
cd zxing-wasm
# install pnpm first:
# Install pnpm first:
# https://pnpm.io/installation
pnpm i --frozen-lockfile
# install cmake first:
# Install CMake first:
# https://cmake.org/download/
pnpm cmake
# install emscripten first:
# Install Emscripten first:
# https://emscripten.org/docs/getting_started/downloads.html
pnpm build:wasm
pnpm build
Expand All @@ -33,55 +33,44 @@ npm i zxing-wasm

https://zxing-wasm.deno.dev/

## Demo
<!-- ## Demo
Demo page: https://zxing-wasm-demo.deno.dev/
Demo source: https://github.com/Sec-ant/zxing-wasm-demo
Demo source: https://github.com/Sec-ant/zxing-wasm-demo -->

## Usage

This package exports 3 subpaths: `full`, `reader` and `writer`. You can choose whichever fits your needs. If you use TypeScript, you should set [`moduleResolution`](https://www.typescriptlang.org/docs/handbook/modules/theory.html#module-resolution) to [`bundler`](https://www.typescriptlang.org/docs/handbook/modules/reference.html#bundler), [`node16` or `nodenext`](https://www.typescriptlang.org/docs/handbook/modules/reference.html#node16-nodenext-1) in your `tsconfig.json` file to properly resolve the exported module.
This package exports three subpaths: `full`, `reader`, and `writer`. You can choose the one that fits your needs. If you use TypeScript, you should set [`moduleResolution`](https://www.typescriptlang.org/docs/handbook/modules/theory.html#module-resolution) to [`bundler`](https://www.typescriptlang.org/docs/handbook/modules/reference.html#bundler), [`node16`, or `nodenext`](https://www.typescriptlang.org/docs/handbook/modules/reference.html#node16-nodenext-1) in your `tsconfig.json` file to properly resolve the exported module.

### `zxing-wasm` or `zxing-wasm/full`

These 2 subpaths include functions to both read and write barcodes. The wasm binary size is ~1.19 MB.
These two subpaths provide functions to read and write barcodes. The wasm binary size is ~1.30 MB.

```ts
import {
readBarcodesFromImageFile,
readBarcodesFromImageData,
writeBarcodeToImageFile,
} from "zxing-wasm";
import { readBarcodes, writeBarcode } from "zxing-wasm";
```

or

```ts
import {
readBarcodesFromImageFile,
readBarcodesFromImageData,
writeBarcodeToImageFile,
} from "zxing-wasm/full";
import { readBarcodes, writeBarcode } from "zxing-wasm/full";
```

### `zxing-wasm/reader`

This subpath only includes functions to read barcodes. The wasm binary size is ~917 KB.
This subpath only provides a function to read barcodes. The wasm binary size is ~906 KB.

```ts
import {
readBarcodesFromImageFile,
readBarcodesFromImageData,
} from "zxing-wasm/reader";
import { readBarcodes } from "zxing-wasm/reader";
```

### `zxing-wasm/writer`

This subpath only includes a function to write barcodes. The wasm binary size is ~366 KB.
This subpath only provides a function to write barcodes. The wasm binary size is ~1.17 MB.

```ts
import { writeBarcodeToImageFile } from "zxing-wasm/writer";
import { writeBarcode } from "zxing-wasm/writer";
```

### IIFE Scripts
Expand All @@ -99,26 +88,16 @@ Apart from ES and CJS modules, this package also ships IIFE scripts. The registe
<script src="https://cdn.jsdelivr.net/npm/zxing-wasm@<version>/dist/iife/writer/index.js"></script>
```

### [`readBarcodesFromImageFile`](https://zxing-wasm.deno.dev/functions/full.readBarcodesFromImageFile.html) and [`readBarcodesFromImageData`](https://zxing-wasm.deno.dev/functions/full.readBarcodesFromImageData.html)
### [`readBarcodes`](https://zxing-wasm.deno.dev/functions/full.readBarcodes.html)

These 2 functions are for reading barcodes.
[`readBarcodes`](https://zxing-wasm.deno.dev/functions/full.readBarcodes.html) accepts an image [`Blob`](https://developer.mozilla.org/docs/Web/API/Blob), image [`File`](https://developer.mozilla.org/docs/Web/API/File), or an [`ImageData`](https://developer.mozilla.org/docs/Web/API/ImageData) as its first argument, and various [`ReaderOptions`](https://zxing-wasm.deno.dev/interfaces/full.ReaderOptions.html) can be set in its optional second argument.

[`readBarcodesFromImageFile`](https://zxing-wasm.deno.dev/functions/full.readBarcodesFromImageFile.html) accepts an image [`Blob`](https://developer.mozilla.org/docs/Web/API/Blob) or an image [`File`](https://developer.mozilla.org/docs/Web/API/File) as the first input. They're encoded images, e.g. `.png` `.jpg` files.

[`readBarcodesFromImageData`](https://zxing-wasm.deno.dev/functions/full.readBarcodesFromImageData.html) accepts an [`ImageData`](https://developer.mozilla.org/docs/Web/API/ImageData) as the first input. They're raw pixels that usually acquired from [`<canvas>`](https://developer.mozilla.org/docs/Web/HTML/Element/canvas) or related APIs.

Both of these 2 functions optionally accept the same second input: [`ReaderOptions`](https://zxing-wasm.deno.dev/interfaces/full.ReaderOptions.html).

The return result of these 2 functions is a `Promise` of an array of [`ReadResult`](https://zxing-wasm.deno.dev/interfaces/full.ReadResult.html)s.
The return result of this function is a `Promise` of an array of [`ReadResult`](https://zxing-wasm.deno.dev/interfaces/full.ReadResult.html)s.

e.g.

```ts
import {
readBarcodesFromImageFile,
readBarcodesFromImageData,
type ReaderOptions,
} from "zxing-wasm/reader";
import { readBarcodes, type ReaderOptions } from "zxing-wasm/reader";

const readerOptions: ReaderOptions = {
tryHarder: true,
Expand All @@ -133,10 +112,7 @@ const imageFile = await fetch(
"https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=Hello%20world!",
).then((resp) => resp.blob());

const imageFileReadResults = await readBarcodesFromImageFile(
imageFile,
readerOptions,
);
const imageFileReadResults = await readBarcodes(imageFile, readerOptions);

console.log(imageFileReadResults[0].text); // Hello world!

Expand All @@ -152,67 +128,75 @@ const imageData = await createImageBitmap(imageFile).then((imageBitmap) => {
return context.getImageData(0, 0, width, height);
});

const imageDataReadResults = await readBarcodesFromImageData(
imageData,
readerOptions,
);
const imageDataReadResults = await readBarcodes(imageData, readerOptions);

console.log(imageDataReadResults[0].text); // Hello world!
```

### [`writeBarcodeToImageFile`](https://zxing-wasm.deno.dev/functions/full.writeBarcodeToImageFile.html)
### [`writeBarcode`](https://zxing-wasm.deno.dev/functions/full.writeBarcode.html)

This function is used to write barcodes. The first argument of this function is a text string to be encoded and the optional second argument is an [`WriterOptions`](https://zxing-wasm.deno.dev/interfaces/full.WriterOptions.html).
The first argument of [`writeBarcode`](https://zxing-wasm.deno.dev/functions/full.writeBarcode.html) is a text string or a [`Uint8Array`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) of bytes to be encoded, and the optional second argument accepts various [`WriterOptions`](https://zxing-wasm.deno.dev/interfaces/full.WriterOptions.html).

The return result of this function is a `Promise` of a [`WriteResult`](https://zxing-wasm.deno.dev/interfaces/full.WriteResult.html).

e.g.

```ts
import { writeBarcodeToImageFile, type WriterOptions } from "zxing-wasm/writer";
import { writeBarcode, type WriterOptions } from "zxing-wasm/writer";

const writerOptions: WriterOptions = {
format: "QRCode",
width: 150,
height: 150,
margin: 10,
eccLevel: 2,
scale: 3,
};

const writeOutput = await writeBarcodeToImageFile(
"Hello world!",
writerOptions,
);
const writeOutput = await writeBarcode("Hello world!", writerOptions);

console.log(writeOutput.image);
console.log(writeOutput.svg); // An SVG string.
console.log(writeOutput.utf8); // A string made up of " ", "▀", "▄", "█" characters.
console.log(writeOutput.image); // A PNG image blob.
```

## Notes

When using this package, the `.wasm` binary needs to be served along with the JS glue code. In order to provide a smooth dev experience, the serve path is automatically assigned the [jsDelivr CDN](https://fastly.jsdelivr.net/npm/zxing-wasm/) url upon build.
When using this package, the `.wasm` binary needs to be served along with the JS glue code. In order to provide a smooth development experience, the serve path is automatically assigned the [jsDelivr CDN](https://fastly.jsdelivr.net/npm/zxing-wasm/) URL upon build.

If you would like to change the serve path (to one of your local network hosts, some other CDNs, or just Base64 encoded data URIs), please use [`setZXingModuleOverrides`](https://zxing-wasm.deno.dev/functions/full.setZXingModuleOverrides.html) to override the [`locateFile`](https://emscripten.org/docs/api_reference/module.html?highlight=locatefile#Module.locateFile) function in advance. `locateFile` is one of the [Emscripten `Module` attribute hooks](https://emscripten.org/docs/api_reference/module.html?highlight=locatefile#affecting-execution) that can affect the code execution of the `Module` object during its lifecycles.
If you would like to change the serve path (to one of your local network hosts, other CDNs, or just Base64-encoded data URIs), please use [`setZXingModuleOverrides`](https://zxing-wasm.deno.dev/functions/full.setZXingModuleOverrides.html) to override the [`locateFile`](https://emscripten.org/docs/api_reference/module.html?highlight=locatefile#Module.locateFile) function in advance. `locateFile` is one of the [Emscripten `Module` attribute hooks](https://emscripten.org/docs/api_reference/module.html#affecting-execution) that can affect the code execution of the `Module` object during its lifecycle.

e.g.

```ts
import { setZXingModuleOverrides, writeBarcodeToImageFile } from "zxing-wasm";
import { setZXingModuleOverrides, writeBarcode } from "zxing-wasm";

// override the locateFile function
// Override the locateFile function
setZXingModuleOverrides({
locateFile: (path, prefix) => {
if (path.endsWith(".wasm")) {
return `https://unpkg.com/zxing-wasm@1/dist/full/${path}`;
return `https://unpkg.com/zxing-wasm@2/dist/full/${path}`;
}
return prefix + path;
},
});

// call read or write functions afterwards
const writeOutput = await writeBarcodeToImageFile("Hello world!");
// Call read or write functions afterward
const writeOutput = await writeBarcode("Hello world!");
```

The wasm binary won't be fetched or instantiated unless a [read](#readbarcodesfromimagefile-and-readbarcodesfromimagedata) or [write](#writebarcodetoimagefile) function is firstly called, and will only be instantiated once given the same ([`Object.is`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/is)) [ZXingModuleOverrides](https://zxing-wasm.deno.dev/types/full.ZXingModuleOverrides). If you want to manually trigger the download and instantiation of the wasm binary prior to any read or write functions, you can use [`getZXingModule`](https://zxing-wasm.deno.dev/functions/full.getZXingModule). This function will also return a `Promise` that resolves to a [`ZXingModule`](https://zxing-wasm.deno.dev/types/full.ZXingModule).
> [!NOTE]
> Each version of this library has a unique corresponding `.wasm` file. If you choose to serve it yourself, ensure that the `.wasm` file matches the version of the `zxing-wasm` library you are using.
>
> For convenience, this library provides an exported `VERSION` variable to easily determine the version of `zxing-wasm` you are using:
>
> ```ts
> import { VERSION } from "zxing-wasm";
> ```
>
> In addition to finding the `.wasm` files by searching in your `node_modules` folder, the `.wasm` files can also be downloaded from CDNs like [jsDelivr](https://cdn.jsdelivr.net/npm/zxing-wasm@latest/dist/):
>
> - **`zxing_full.wasm`**: `https://cdn.jsdelivr.net/npm/zxing-wasm@<version>/dist/full/zxing_full.wasm`
> - **`zxing_reader.wasm`**: `https://cdn.jsdelivr.net/npm/zxing-wasm@<version>/dist/reader/zxing_reader.wasm`
> - **`zxing_writer.wasm`**: `https://cdn.jsdelivr.net/npm/zxing-wasm@<version>/dist/writer/zxing_writer.wasm`
The wasm binary won't be fetched or instantiated unless a [read](#readbarcodes) or [write](#writebarcode) function is first called, and will only be instantiated once given the same ([`Object.is`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/is)) [ZXingModuleOverrides](https://zxing-wasm.deno.dev/types/full.ZXingModuleOverrides.html). If you want to manually trigger the download and instantiation of the wasm binary prior to any read or write functions, you can use [`getZXingModule`](https://zxing-wasm.deno.dev/functions/full.getZXingModule). This function will also return a `Promise` that resolves to a [`ZXingModule`](https://zxing-wasm.deno.dev/types/full.ZXingModule).
```ts
import { getZXingModule } from "zxing-wasm";
Expand All @@ -236,7 +220,7 @@ import { getZXingModule } from "zxing-wasm";
getZXingModule({
locateFile: (path, prefix) => {
if (path.endsWith(".wasm")) {
return `https://unpkg.com/zxing-wasm@1/dist/full/${path}`;
return `https://unpkg.com/zxing-wasm@2/dist/full/${path}`;
}
return prefix + path;
},
Expand Down
35 changes: 31 additions & 4 deletions biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,37 @@
},
"overrides": [
{
"include": ["*.json"],
"json": {
"parser": {
"allowTrailingCommas": true
"include": [
"core.ts",
"full/index.ts",
"reader/index.ts",
"writer/index.ts"
],
"linter": {
"rules": {
"suspicious": {
"noConfusingVoidType": "off"
}
}
}
},
{
"include": ["tests/**/*.ts"],
"linter": {
"rules": {
"performance": {
"noDelete": "off"
}
}
}
},
{
"include": ["imageData.d.ts"],
"linter": {
"rules": {
"complexity": {
"noBannedTypes": "off"
}
}
}
},
Expand Down
37 changes: 24 additions & 13 deletions main.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
import {
readBarcodesFromImageFile,
writeBarcodeToImageFile,
type ReaderOptions,
type WriterOptions,
readBarcodes,
writeBarcode,
} from "./src/full/index";

// import { readBarcodesFromImageFile } from "./src/reader/index";
const imageFile = await fetch(
"https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=Hello%20world!",
).then((resp) => resp.blob());

// import { writeBarcodeToImageFile } from "./src/writer/index";
const readerOptions: ReaderOptions = {
tryHarder: true,
formats: ["QRCode"],
maxNumberOfSymbols: 1,
};

const text = "Hello World!";
const barcodeImage = (await writeBarcodeToImageFile(text)).image;
if (barcodeImage) {
const readResults = await readBarcodesFromImageFile(barcodeImage, {
formats: ["QRCode"],
});
console.log(readResults);
console.log(readResults[0].text === text);
}
const imageFileReadResults = await readBarcodes(imageFile, readerOptions);

console.log(imageFileReadResults); // Hello world!

const writerOptions: WriterOptions = {
format: "EAN-13",
scale: 0,
withQuietZones: true,
withHRT: false,
};

console.log(await writeBarcode("12345", writerOptions));
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@
"vitest": "^2.1.8"
},
"dependencies": {
"@types/emscripten": "^1.39.13"
"@types/emscripten": "^1.39.13",
"type-fest": "^4.30.1"
},
"overrides": {
"typedoc": {
Expand Down
9 changes: 9 additions & 0 deletions pnpm-lock.yaml

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

Loading

0 comments on commit f5cdf80

Please sign in to comment.