@liquid-js/qr-code-styling 2.0.5 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,8 +20,14 @@ If you have issues / suggestions / notes / questions, please open an issue or co
20
20
 
21
21
  npm install @liquid-js/qr-code-styling
22
22
 
23
+ ### API Documentation
24
+
25
+ <https://liquid-js.github.io/qr-code-styling/>
26
+
23
27
  ### Usage
24
28
 
29
+ #### Browser
30
+
25
31
  ```HTML
26
32
  <!doctype html>
27
33
  <html lang="en">
@@ -33,28 +39,29 @@ If you have issues / suggestions / notes / questions, please open an issue or co
33
39
  <div id="canvas"></div>
34
40
  <button type="button" id="dl">Download</button>
35
41
  <script type="module">
36
- import { QRCodeStyling, browserUtils } from "./index.ts";
42
+ import { QRCodeStyling, browserUtils } from "https://unpkg.com/@liquid-js/qr-code-styling/lib/qr-code-styling.js";
37
43
 
38
44
  const qrCode = new QRCodeStyling({
39
- width: 300,
40
- height: 300,
41
- type: "svg",
42
45
  data: "https://www.facebook.com/",
43
46
  image: "https://upload.wikimedia.org/wikipedia/commons/5/51/Facebook_f_logo_%282019%29.svg",
44
47
  dotsOptions: {
45
48
  color: "#4267b2",
46
- type: "rounded"
49
+ type: "rounded",
50
+ size: 10
47
51
  },
48
52
  backgroundOptions: {
49
- color: "#e9ebee"
53
+ color: "#e9ebee",
54
+ margin: 1
50
55
  },
51
56
  imageOptions: {
52
57
  crossOrigin: "anonymous",
53
- margin: 20
58
+ margin: 1,
59
+ imageSize: 0.9
54
60
  }
55
61
  });
56
62
 
57
63
  qrCode.append(document.getElementById("canvas"));
64
+
58
65
  document.getElementById("dl").addEventListener("click", () => {
59
66
  browserUtils.download(qrCode, { extension: "png" }, { width: 1200, height: 1200 });
60
67
  });
@@ -63,170 +70,52 @@ If you have issues / suggestions / notes / questions, please open an issue or co
63
70
  </html>
64
71
  ```
65
72
 
66
- ### API Documentation
67
-
68
- #### QRCodeStyling instance
69
-
70
- ```js
71
- new QRCodeStyling(options) => QRCodeStyling
72
- ```
73
-
74
- | Param | Type | Description |
75
- | ------- | ------ | ----------- |
76
- | options | object | Init object |
77
-
78
- `options` structure
79
-
80
- | Property | Type | Default Value | Description |
81
- | -------------------- | ----------------- | ------------- | ---------------------------------------------------------- |
82
- | data | string | | The date will be encoded to the QR code |
83
- | image | string \| Blob | | The image will be copied to the center of the QR code |
84
- | shape | string | `'square'` | QR code shape |
85
- | qrOptions | object | | Options will be passed to `qrcode-generator` lib |
86
- | imageOptions | object | | Specific image options, details see below |
87
- | dotsOptions | object | | Dots styling options |
88
- | cornersSquareOptions | object | | Square in the corners styling options |
89
- | cornersDotOptions | object | | Dots in the corners styling options |
90
- | backgroundOptions | object \| boolean | `false` | QR background styling options, false to disable background |
91
-
92
- `options.qrOptions` structure
93
-
94
- | Property | Type | Default Value |
95
- | -------------------- | -------------------------------------------------- | ------------- |
96
- | typeNumber | number (`0 - 40`) | `0` |
97
- | mode | string (`'Numeric' 'Alphanumeric' 'Byte' 'Kanji'`) | |
98
- | errorCorrectionLevel | string (`'L' 'M' 'Q' 'H'`) | `'Q'` |
99
-
100
- `options.imageOptions` structure
101
-
102
- | Property | Type | Default Value | Description |
103
- | ------------------ | ---------------------------------------- | ------------- | ------------------------------------------------------------------------------ |
104
- | hideBackgroundDots | boolean | `true` | Hide all dots covered by the image |
105
- | imageSize | number | `0.4` | Coefficient of the image size. Not recommended to use ove 0.5. Lower is better |
106
- | margin | number | `0` | Margin of the image (in blocks) |
107
- | crossOrigin | string (`'anonymous' 'use-credentials'`) | | Set "anonymous" if you want to download QR code from other origins. |
108
-
109
- `options.dotsOptions` structure
110
-
111
- | Property | Type | Default Value | Description |
112
- | -------- | ------------------------------------------------------------------------------ | ------------- | ----------------------- |
113
- | size | number | `10` | QR dot size (in pixels) |
114
- | color | string | `'#000'` | Color of QR dots |
115
- | gradient | object | | Gradient of QR dots |
116
- | type | string (`'rounded' 'dots' 'classy' 'classy-rounded' 'square' 'extra-rounded'`) | `'square'` | Style of QR dots |
117
-
118
- `options.cornersSquareOptions` structure
119
-
120
- | Property | Type | Default Value | Description |
121
- | -------- | ----------------------------------------- | ------------- | -------------------------- |
122
- | color | string | | Color of Corners Square |
123
- | gradient | object | | Gradient of Corners Square |
124
- | type | string (`'dot' 'square' 'extra-rounded'`) | | Style of Corners Square |
125
-
126
- `options.cornersDotOptions` structure
127
-
128
- | Property | Type | Default Value | Description |
129
- | -------- | ------------------------- | ------------- | ----------------------- |
130
- | color | string | | Color of Corners Dot |
131
- | gradient | object | | Gradient of Corners Dot |
132
- | type | string (`'dot' 'square'`) | | Style of Corners Dot |
133
-
134
- `options.backgroundOptions` structure
135
-
136
- | Property | Type | Default Value | Description |
137
- | -------- | ---------------- | ------------- | ----------------------------------------------------- |
138
- | round | number (`0 - 1`) | `0` | Background roundnes |
139
- | color | string | | |
140
- | gradient | object | | |
141
- | margin | number | `0` | Margin (in blocks) between background and the QR code |
142
-
143
- Gradient structure
144
-
145
- `options.dotsOptions.gradient`
146
-
147
- `options.backgroundOptions.gradient`
148
-
149
- `options.cornersSquareOptions.gradient`
150
-
151
- `options.cornersDotOptions.gradient`
152
-
153
- | Property | Type | Default Value | Description |
154
- | ---------- | ---------------------------- | ------------- | --------------------------------------------------------------------------------------- |
155
- | type | string (`'linear' 'radial'`) | `'linear'` | Type of gradient spread |
156
- | rotation | number | 0 | Rotation of gradient in radians (Math.PI === 180 degrees) |
157
- | colorStops | array of objects | | Gradient colors. Example `[{ offset: 0, color: 'blue' }, { offset: 1, color: 'red' }]` |
158
-
159
- Gradient colorStops structure
160
-
161
- `options.dotsOptions.gradient.colorStops[]`
162
-
163
- `options.backgroundOptions.gradient.colorStops[]`
164
-
165
- `options.cornersSquareOptions.gradient.colorStops[]`
166
-
167
- `options.cornersDotOptions.gradient.colorStops[]`
168
-
169
- | Property | Type | Default Value | Description |
170
- | -------- | ---------------- | ------------- | ----------------------------------- |
171
- | offset | number (`0 - 1`) | | Position of color in gradient range |
172
- | color | string | | Color of stop in gradient range |
173
-
174
- #### QRCodeStyling methods
175
-
176
- ```js
177
- QRCodeStyling.append(container) => void
178
- ```
179
-
180
- | Param | Type | Description |
181
- | --------- | ----------- | -------------------------------------------------------- |
182
- | container | DOM element | This container will be used for appending of the QR code |
73
+ #### Node
183
74
 
184
75
  ```js
185
- QRCodeStyling.serialize() => Promise<string>
186
- ```
187
-
188
- ```js
189
- QRCodeStyling.update(options) => void
190
- ```
191
-
192
- | Param | Type | Description |
193
- | ------- | ------ | -------------------------------------- |
194
- | options | object | The same options as for initialization |
195
-
196
- ```js
197
- QRCodeStyling.applyExtension(extension) => void
198
- ```
199
-
200
- | Param | Type | Description |
201
- | --------- | ---------------------- | ----------------------------------------------------------------------------------------- |
202
- | extension | (svg, options) => void | Extension is a function that takes svg and previously applied options and modifies an svg |
203
-
204
- `applyExtension` example
205
-
206
- ```js
207
- const extension = (svg, options) => {
208
- const { width, height } = options;
209
- const size = Math.min(width, height);
210
- const border = document.createElementNS("http://www.w3.org/2000/svg", "rect");
211
- const borderAttributes = {
212
- fill: "none",
213
- x: (width - size + 40) / 2,
214
- y: (height - size + 40) / 2,
215
- width: size - 40,
216
- height: size - 40,
217
- stroke: "black",
218
- "stroke-width": 40,
219
- rx: 100
220
- };
221
- Object.keys(borderAttributes).forEach((attribute) => {
222
- border.setAttribute(attribute, borderAttributes[attribute]);
76
+ import { QRCodeStyling } from "@liquid-js/qr-code-styling";
77
+ import { writeFile } from "fs/promises";
78
+ import PDFDocument from "pdfkit";
79
+ import SVGtoPDF from "svg-to-pdfkit";
80
+
81
+ const qrCode = new QRCodeStyling({
82
+ data: "https://www.facebook.com/",
83
+ image: "https://upload.wikimedia.org/wikipedia/commons/5/51/Facebook_f_logo_%282019%29.svg",
84
+ dotsOptions: {
85
+ color: "#4267b2",
86
+ type: "rounded",
87
+ size: 10
88
+ },
89
+ backgroundOptions: {
90
+ color: "#e9ebee",
91
+ margin: 1
92
+ },
93
+ imageOptions: {
94
+ crossOrigin: "anonymous",
95
+ margin: 1,
96
+ imageSize: 0.9
97
+ }
98
+ });
99
+
100
+ const svgCode = await qrCode.serialize();
101
+
102
+ const width = parseFloat(qrCode._svg.getAttribute("width"));
103
+ const height = parseFloat(qrCode._svg.getAttribute("height"));
104
+ const buffers = [];
105
+ const doc = new PDFDocument({ size: [width, height] });
106
+ doc.on("data", (v) => buffers.push(v));
107
+ const buffer = await new Promise((resolve) => {
108
+ doc.on("end", () => {
109
+ resolve(Buffer.concat(buffers));
223
110
  });
224
- svg.appendChild(border);
225
- };
226
- ```
227
-
228
- ```js
229
- QRCodeStyling.deleteExtension() => void
111
+ SVGtoPDF(doc, svgCode, 0, 0, {
112
+ width,
113
+ height,
114
+ assumePt: true
115
+ });
116
+ doc.end();
117
+ });
118
+ await writeFile("qr.pdf", buffer);
230
119
  ```
231
120
 
232
121
  ### License
@@ -1,19 +1,60 @@
1
1
  import { ExtensionFunction, Options, QRCode } from "../types";
2
2
  import { RequiredOptions } from "./QROptions";
3
3
  export declare class QRCodeStyling {
4
+ /** @ignore */
4
5
  _options: RequiredOptions;
6
+ /** @ignore */
5
7
  _container?: HTMLElement;
8
+ /** @ignore */
6
9
  _svg?: SVGElement;
10
+ /** @ignore */
7
11
  _qr?: QRCode;
12
+ /** @ignore */
8
13
  _extension?: ExtensionFunction;
14
+ /** @ignore */
9
15
  _svgDrawingPromise?: Promise<void>;
10
16
  constructor(options?: Partial<Options>);
17
+ /** @ignore */
11
18
  static _clearContainer(container?: HTMLElement): void;
19
+ /** @ignore */
12
20
  _setupSvg(): void;
21
+ /** @ignore */
13
22
  _getElement(): Promise<SVGElement | undefined>;
14
- update(options?: Partial<Options>): void;
15
- append(container?: HTMLElement): void;
16
- applyExtension(extension: ExtensionFunction): void;
23
+ update(
24
+ /** The same options as for initialization */
25
+ options?: Partial<Options>): void;
26
+ append(
27
+ /** This container will be used for appending of the QR code */
28
+ container?: HTMLElement): void;
29
+ /**
30
+ *
31
+ * @example
32
+ *
33
+ * ```js
34
+ * const extension = (svg, options) => {
35
+ * const { width, height } = options;
36
+ * const size = Math.min(width, height);
37
+ * const border = document.createElementNS("http://www.w3.org/2000/svg", "rect");
38
+ * const borderAttributes = {
39
+ * fill: "none",
40
+ * x: (width - size + 40) / 2,
41
+ * y: (height - size + 40) / 2,
42
+ * width: size - 40,
43
+ * height: size - 40,
44
+ * stroke: "black",
45
+ * "stroke-width": 40,
46
+ * rx: 100
47
+ * };
48
+ * Object.keys(borderAttributes).forEach((attribute) => {
49
+ * border.setAttribute(attribute, borderAttributes[attribute]);
50
+ * });
51
+ * svg.appendChild(border);
52
+ * };
53
+ * ```
54
+ */
55
+ applyExtension(
56
+ /** Extension is a function that takes svg and previously applied options and modifies an svg */
57
+ extension: ExtensionFunction): void;
17
58
  deleteExtension(): void;
18
59
  serialize(): Promise<string | undefined>;
19
60
  }
@@ -1,15 +1,25 @@
1
1
  import { FilterFunction, Gradient, QRCode } from "../types";
2
2
  import { RequiredOptions } from "./QROptions";
3
3
  export declare class QRSVG {
4
+ /** @ignore */
4
5
  _element: SVGElement;
6
+ /** @ignore */
5
7
  _defs: SVGElement;
8
+ /** @ignore */
6
9
  _backgroundClipPath?: SVGElement;
10
+ /** @ignore */
7
11
  _dotsClipPath?: SVGElement;
12
+ /** @ignore */
8
13
  _cornersSquareClipPath?: SVGElement;
14
+ /** @ignore */
9
15
  _cornersDotClipPath?: SVGElement;
16
+ /** @ignore */
10
17
  _options: RequiredOptions;
18
+ /** @ignore */
11
19
  _qr?: QRCode;
20
+ /** @ignore */
12
21
  _document: Document;
22
+ /** @ignore */
13
23
  private _imageTools;
14
24
  constructor(options: RequiredOptions);
15
25
  get width(): number;
@@ -25,6 +35,7 @@ export declare class QRSVG {
25
35
  count: number;
26
36
  dotSize: number;
27
37
  }): Promise<void>;
38
+ /** @ignore */
28
39
  _createColor({ options, color, additionalRotation, x, y, height, width, name }: {
29
40
  options?: Gradient;
30
41
  color?: string;
@@ -642,7 +642,7 @@ const browserImageTools = {
642
642
  return reject("Image is not defined");
643
643
  }
644
644
  const image = new Image();
645
- if (typeof options.imageOptions.crossOrigin === "string") {
645
+ if (typeof options.imageOptions?.crossOrigin === "string") {
646
646
  image.crossOrigin = options.imageOptions.crossOrigin;
647
647
  }
648
648
  image.onload = () => {
@@ -890,7 +890,7 @@ class QRSVG {
890
890
  if (filter && !filter(i, j)) {
891
891
  continue;
892
892
  }
893
- if (!this._qr?.isDark(i, j)) {
893
+ if (!this._qr?.isDark(j, i)) {
894
894
  continue;
895
895
  }
896
896
  dot.draw(xBeginning + i * dotSize, yBeginning + j * dotSize, dotSize, (xOffset, yOffset) => {
@@ -898,7 +898,7 @@ class QRSVG {
898
898
  return false;
899
899
  if (filter && !filter(i + xOffset, j + yOffset))
900
900
  return false;
901
- return !!this._qr && this._qr.isDark(i + xOffset, j + yOffset);
901
+ return !!this._qr && this._qr.isDark(j + yOffset, i + xOffset);
902
902
  });
903
903
  if (dot._element && this._dotsClipPath) {
904
904
  this._dotsClipPath.appendChild(dot._element);
@@ -1093,6 +1093,7 @@ class QRSVG {
1093
1093
  image.setAttribute("height", `${dh}px`);
1094
1094
  this._element.appendChild(image);
1095
1095
  }
1096
+ /** @ignore */
1096
1097
  _createColor({ options, color, additionalRotation, x, y, height, width, name }) {
1097
1098
  const size = width > height ? width : height;
1098
1099
  const rect = this._document.createElementNS("http://www.w3.org/2000/svg", "rect");
@@ -1174,11 +1175,13 @@ let QRCodeStyling$1 = class QRCodeStyling {
1174
1175
  this._options = options ? sanitizeOptions(mergeDeep(defaultOptions, options)) : defaultOptions;
1175
1176
  this.update();
1176
1177
  }
1178
+ /** @ignore */
1177
1179
  static _clearContainer(container) {
1178
1180
  if (container) {
1179
1181
  container.innerHTML = "";
1180
1182
  }
1181
1183
  }
1184
+ /** @ignore */
1182
1185
  _setupSvg() {
1183
1186
  if (!this._qr) {
1184
1187
  return;
@@ -1198,6 +1201,7 @@ let QRCodeStyling$1 = class QRCodeStyling {
1198
1201
  this._extension?.(qrSVG.getElement(), this._options);
1199
1202
  });
1200
1203
  }
1204
+ /** @ignore */
1201
1205
  async _getElement() {
1202
1206
  if (!this._qr)
1203
1207
  throw "QR code is empty";
@@ -1207,7 +1211,9 @@ let QRCodeStyling$1 = class QRCodeStyling {
1207
1211
  await this._svgDrawingPromise;
1208
1212
  return this._svg;
1209
1213
  }
1210
- update(options) {
1214
+ update(
1215
+ /** The same options as for initialization */
1216
+ options) {
1211
1217
  QRCodeStyling._clearContainer(this._container);
1212
1218
  this._options = options ? sanitizeOptions(mergeDeep(this._options, options)) : this._options;
1213
1219
  if (!this._options.data) {
@@ -1219,7 +1225,9 @@ let QRCodeStyling$1 = class QRCodeStyling {
1219
1225
  this._setupSvg();
1220
1226
  this.append(this._container);
1221
1227
  }
1222
- append(container) {
1228
+ append(
1229
+ /** This container will be used for appending of the QR code */
1230
+ container) {
1223
1231
  if (!container) {
1224
1232
  return;
1225
1233
  }
@@ -1231,7 +1239,35 @@ let QRCodeStyling$1 = class QRCodeStyling {
1231
1239
  }
1232
1240
  this._container = container;
1233
1241
  }
1234
- applyExtension(extension) {
1242
+ /**
1243
+ *
1244
+ * @example
1245
+ *
1246
+ * ```js
1247
+ * const extension = (svg, options) => {
1248
+ * const { width, height } = options;
1249
+ * const size = Math.min(width, height);
1250
+ * const border = document.createElementNS("http://www.w3.org/2000/svg", "rect");
1251
+ * const borderAttributes = {
1252
+ * fill: "none",
1253
+ * x: (width - size + 40) / 2,
1254
+ * y: (height - size + 40) / 2,
1255
+ * width: size - 40,
1256
+ * height: size - 40,
1257
+ * stroke: "black",
1258
+ * "stroke-width": 40,
1259
+ * rx: 100
1260
+ * };
1261
+ * Object.keys(borderAttributes).forEach((attribute) => {
1262
+ * border.setAttribute(attribute, borderAttributes[attribute]);
1263
+ * });
1264
+ * svg.appendChild(border);
1265
+ * };
1266
+ * ```
1267
+ */
1268
+ applyExtension(
1269
+ /** Extension is a function that takes svg and previously applied options and modifies an svg */
1270
+ extension) {
1235
1271
  if (!extension) {
1236
1272
  throw "Extension function should be defined.";
1237
1273
  }