Skip to content

Commit

Permalink
docs: update readme, examples & diagrams
Browse files Browse the repository at this point in the history
  • Loading branch information
xseman committed Dec 26, 2024
1 parent 9e3e6a4 commit 702cc30
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 529 deletions.
3 changes: 2 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"recommendations": [
"dprint.dprint",
"editorconfig.editorconfig",
"hediet.vscode-drawio",
"editorconfig.editorconfig"
"pomdtr.excalidraw-editor"
]
}
83 changes: 27 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@
the Slovak Banking Association in 2013. It is incorporated into a variety of
invoices, reminders and other payment regulations.

## What it is
## Why

- Simple JavaScript library to encode and decode "PAY by square" string.
- Aim to support simpe programming interface to encode and decode data for QR.
It's simple, I couldn't find any implementation of "PAY by square" standard for
JavaScript, so I decided to create one and share it with the community to help
individuals and businesses to create QR codes for their invoices.

## What it is not
## Features

- Generating QR code images.
- Parsing QR code images.
- TypeScript support
- Compatible with Slovak banking apps
- Runtime-independent JavaScript implementation

## Installation

Expand All @@ -24,30 +26,13 @@ invoices, reminders and other payment regulations.
[mozzila-esm]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules
[mozzila-import]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import

### npm registry
### npm

```sh
npm install bysquare
$ npm install bysquare
```

### CLI Node `v18+`

```sh
npm install --global bysquare
```

### deno

Since `v1.28+` import from npm registry using `npm:` prefix.

```ts
import {
decode,
encode,
} from "npm:bysquare@latest";
```

### Browser
### browser

```html
<script type="module">
Expand Down Expand Up @@ -80,6 +65,14 @@ const qrstring = simplePayment({

For more complex data use `encode` and `decode` functions:

> [!NOTE]
> Encoded data are without diacritics
>
> The library removes all diacritics from the input data to ensure maximum
> compatibility, as not all banks support diacritics, which may lead to errors.
> If you need to retain diacritics, disable deburr option when encoding data -
> `encode(model, { deburr: false })`.
```ts
import {
CurrencyCode,
Expand Down Expand Up @@ -113,13 +106,17 @@ const model = decode(qrstring);

## CLI

```sh
$ npm install --global bysquare
```

### Encode

Encode JSON or JSONL data from files and print the corresponding QR code.

```sh
npx bysquare --encode file1.json file2.json...
npx bysquare --encode file.jsonl
$ bysquare --encode file1.json file2.json...
$ bysquare --encode file.jsonl
```

### Decode
Expand All @@ -128,40 +125,14 @@ Decode the specified QR code string and print the corresponding JSON data. The
qrstring argument should be a valid QR code string.

```sh
npx bysquare --decode <qrstring>
$ bysquare --decode <qrstring>
```

## How it works

### Encoding sequence

![logic](./docs/uml/logic.svg)

## Platform support

I mainly focus on LTS versions of Node.js and try to use the most idiomatic
ECMAScript possible to avoid specific runtime coupling.

This doesn't mean that the library won't work on older versions, but it might
not be as reliable.

As of `v1.28`, Deno now includes built-in support for npm modules and is ready
to use without additional setup, showing its improved maturity.

### Node.js & Deno

- Node.js `v18` and later.
- Deno `v1.28` and later.

### Browser

The latest version of Chrome, Firefox, and Safari.

## Troubleshooting & Recommendations

### Encoded data are without diacritics

The library removes all diacritics from the input data to ensure maximum compatibility, as not all banks support diacritics, which may lead to errors. If you need to retain diacritics, disable deburr option when encoding data - `encode(model, { deburr: false })`.
<image src="./docs/logic.svg" alt="encode" width="500px">

## Related

Expand Down
15 changes: 12 additions & 3 deletions docs/examples/nodejs/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {
CurrencyCode,
type DataModel,
encode,
PaymentOptions,
Periodicity,
} from "./../../../src/index.js";
// import {
// CurrencyCode,
Expand All @@ -10,24 +12,31 @@ import {
// PaymentOptions,
// } from "bysquare";

const encoded = encode({
const data = {
invoiceId: "random-id",
payments: [
{
type: PaymentOptions.PaymentOrder,
type: PaymentOptions.StandingOrder,
amount: 100.0,
bankAccounts: [
{ iban: "SK9611000000002918599669" },
],
currencyCode: CurrencyCode.EUR,
variableSymbol: "123",
paymentNote: "hello world",
day: 1,
periodicity: Periodicity.Monthly,
paymentDueDate: "2024-08-30",
beneficiary: {
name: "Filip",
city: "City",
street: "Street",
},
},
],
});
} satisfies DataModel;

console.log(JSON.stringify(data, null, 4));

const encoded = encode(data);
console.log(encoded);
2 changes: 1 addition & 1 deletion docs/examples/nodejs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"author": "Filip Seman",
"type": "module",
"scripts": {
"start": "node --no-warnings --loader=ts-node/esm ./main.ts"
"start": "TS_NODE_TRANSPILE_ONLY=true node --no-warnings --loader=ts-node/esm ./main.ts"
},
"dependencies": {
"bysquare": "latest"
Expand Down
83 changes: 37 additions & 46 deletions docs/examples/web/basic/index.html
Original file line number Diff line number Diff line change
@@ -1,49 +1,40 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>bysquare example</title>
<script type="module" src="index.js"></script>
</head>
<body>
<div>
<div style="margin-right: 10px;">
<label style="display: block; margin-bottom: 5px;">
Amount:
<br/>
<input
style="width: 210px;"
type="number"
name="amount"
value=""
/>
</label>
<label style="display: block; margin-bottom: 5px;">
IBAN:
<br/>
<input
style="width: 210px;"
name="iban"
/>
</label>
<label style="display: block; margin-bottom: 5px;">
Variable:
<br/>
<input
style="width: 210px;"
type="number"
name="variable"
/>
</label>
<pre id="encodedText"></pre>
<canvas
height="200"
width="200"
id="canvas"
></canvas>
</div>
</div>
</body>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>bysquare example</title>

<script type="module" src="index.js"></script>
</head>

<body>
<div>
<div style="margin-right: 10px">
<label style="display: block; margin-bottom: 5px">
Amount:
<br />
<input
style="width: 210px"
type="number"
name="amount"
value=""
/>
</label>
<label style="display: block; margin-bottom: 5px">
IBAN:
<br />
<input style="width: 210px" name="iban" />
</label>
<label style="display: block; margin-bottom: 5px">
Variable:
<br />
<input style="width: 210px" type="number" name="variable" />
</label>
<pre id="encodedText"></pre>
<div style="width: 200px" id="qrcode"></div>
</div>
</div>
</body>
</html>
92 changes: 51 additions & 41 deletions docs/examples/web/basic/index.js
Original file line number Diff line number Diff line change
@@ -1,60 +1,70 @@
import { QRCode } from "https://esm.sh/@lostinbrittany/qr-esm@latest";
import {
CurrencyCode,
encode,
PaymentOptions,
} from "https://esm.sh/bysquare@latest/";
import { qrcanvas } from "https://esm.sh/qrcanvas@3.1.2/";

function getEncodedText(iban, amount, variable) {
return encode({
invoiceId: new Date().toLocaleDateString("sk"),
payments: [
{
class BysquareQR {
constructor() {
this.amountInput = null;
this.ibanInput = null;
this.variableInput = null;
this.encodedTextDiv = null;
this.qrContainer = null;
}

getEncodedText(iban, amount, variable) {
return encode({
invoiceId: new Date().toLocaleDateString("sk"),
payments: [{
type: PaymentOptions.PaymentOrder,
amount: amount,
bankAccounts: [{ iban: iban }],
currencyCode: CurrencyCode.EUR,
variableSymbol: variable,
},
],
});
}
}],
});
}

function renderOnCanvas(canvasEl, encodedText) {
if (canvasEl) {
const ctx = canvasEl.getContext("2d");
if (ctx) {
ctx.clearRect(0, 0, canvasEl.width, canvasEl.height);
qrcanvas({
data: encodedText,
canvas: canvasEl,
});
}
renderQrCode(container, encodedText) {
container.innerHTML = "";
const svgQr = QRCode.generateSVG(encodedText);
console.log(svgQr);
container.appendChild(svgQr);
}
}

function init() {
const amountInput = document.querySelector('input[name="amount"]');
const ibanInput = document.querySelector('input[name="iban"]');
const variableInput = document.querySelector('input[name="variable"]');
const encodedTextDiv = document.querySelector("#encodedText");
const canvasEl = document.querySelector("#canvas");

amountInput.value = "100";
ibanInput.value = "SK9611000000002918599669";
variableInput.value = "123";

function render() {
const encodedText = getEncodedText(ibanInput.value, amountInput.value, variableInput.value);
encodedTextDiv.innerText = encodedText;
renderOnCanvas(canvasEl, encodedText);
init() {
this.amountInput = document.querySelector('input[name="amount"]');
this.ibanInput = document.querySelector('input[name="iban"]');
this.variableInput = document.querySelector('input[name="variable"]');
this.encodedTextDiv = document.querySelector("#encodedText");
this.qrContainer = document.querySelector("#qrcode");

this.amountInput.value = "100";
this.ibanInput.value = "SK9611000000002918599669";
this.variableInput.value = "123";

this.amountInput.addEventListener("input", this.render);
this.ibanInput.addEventListener("input", this.render);
this.variableInput.addEventListener("input", this.render);

this.render();
}

amountInput.addEventListener("input", render);
ibanInput.addEventListener("input", render);
variableInput.addEventListener("input", render);
render = () => {
const encodedText = this.getEncodedText(
this.ibanInput.value,
this.amountInput.value,
this.variableInput.value,
);

render();
this.encodedTextDiv.innerText = encodedText;
this.renderQrCode(this.qrContainer, encodedText);
};
}

window.addEventListener("load", init);
window.addEventListener("load", () => {
const bysquareQR = new BysquareQR();
bysquareQR.init();
});
Loading

0 comments on commit 702cc30

Please sign in to comment.