@liquid-js/qr-code-styling 2.4.1 → 3.0.0-0

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/LICENSE CHANGED
@@ -2,6 +2,8 @@ MIT License
2
2
 
3
3
  Copyright (c) 2019 Denys Kozak
4
4
 
5
+ Copyright (c) 2023 Liquid-JS
6
+
5
7
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
8
  of this software and associated documentation files (the "Software"), to deal
7
9
  in the Software without restriction, including without limitation the rights
package/README.md CHANGED
@@ -2,11 +2,9 @@
2
2
 
3
3
  [![Version](https://img.shields.io/npm/v/@liquid-js/qr-code-styling.svg)](https://www.npmjs.org/package/@liquid-js/qr-code-styling)
4
4
 
5
- JavaScript library for generating QR codes with a logo and styling.
5
+ JavaScript library for generating QR codes with customizable styling.
6
6
 
7
- Try it here <https://qr-code-styling.com>
8
-
9
- If you have issues / suggestions / notes / questions, please open an issue or contact me. Let's create a cool library together.
7
+ Try it here <https://styled-qr.liquidjs.io/>
10
8
 
11
9
  ## Examples
12
10
 
@@ -6,13 +6,21 @@ export declare class QRSVG {
6
6
  /** @ignore */
7
7
  _defs: SVGElement;
8
8
  /** @ignore */
9
- _backgroundClipPath?: SVGElement;
9
+ _backgroundMask?: SVGElement;
10
10
  /** @ignore */
11
- _dotsClipPath?: SVGElement;
11
+ _backgroundMaskGroup?: SVGElement;
12
12
  /** @ignore */
13
- _cornersSquareClipPath?: SVGElement;
13
+ _dotsMask?: SVGElement;
14
14
  /** @ignore */
15
- _cornersDotClipPath?: SVGElement;
15
+ _dotsMaskGroup?: SVGElement;
16
+ /** @ignore */
17
+ _cornersSquareMask?: SVGElement;
18
+ /** @ignore */
19
+ _cornersSquareMaskGroup?: SVGElement;
20
+ /** @ignore */
21
+ _cornersDotMask?: SVGElement;
22
+ /** @ignore */
23
+ _cornersDotMaskGroup?: SVGElement;
16
24
  /** @ignore */
17
25
  _options: RequiredOptions;
18
26
  /** @ignore */
@@ -46,4 +54,5 @@ export declare class QRSVG {
46
54
  width: number;
47
55
  name: string;
48
56
  }): void;
57
+ _createMask(id: string): (SVGGElement | SVGMaskElement)[];
49
58
  }
@@ -1240,15 +1240,14 @@ class QRSVG {
1240
1240
  });
1241
1241
  const size = Math.min(options.width, options.height);
1242
1242
  const element = this._document.createElementNS("http://www.w3.org/2000/svg", "rect");
1243
- this._backgroundClipPath = this._document.createElementNS("http://www.w3.org/2000/svg", "clipPath");
1244
- this._backgroundClipPath.setAttribute("id", "clip-path-background-color");
1245
- this._defs.appendChild(this._backgroundClipPath);
1243
+ [this._backgroundMask, this._backgroundMaskGroup] = this._createMask("mask-background-color");
1244
+ this._defs.appendChild(this._backgroundMask);
1246
1245
  element.setAttribute("x", String((options.width - size) / 2));
1247
1246
  element.setAttribute("y", String((options.height - size) / 2));
1248
1247
  element.setAttribute("width", String(size));
1249
1248
  element.setAttribute("height", String(size));
1250
1249
  element.setAttribute("rx", String((size / 2) * (options.backgroundOptions.round || 0)));
1251
- this._backgroundClipPath.appendChild(element);
1250
+ this._backgroundMaskGroup.appendChild(element);
1252
1251
  }
1253
1252
  }
1254
1253
  drawDots(filter) {
@@ -1265,9 +1264,8 @@ class QRSVG {
1265
1264
  const xBeginning = Math.floor((options.width - count * dotSize) / 2);
1266
1265
  const yBeginning = Math.floor((options.height - count * dotSize) / 2);
1267
1266
  const dot = new QRDot({ svg: this._element, type: options.dotsOptions.type, document: this._document });
1268
- this._dotsClipPath = this._document.createElementNS("http://www.w3.org/2000/svg", "clipPath");
1269
- this._dotsClipPath.setAttribute("id", "clip-path-dot-color");
1270
- this._defs.appendChild(this._dotsClipPath);
1267
+ [this._dotsMask, this._dotsMaskGroup] = this._createMask("mask-dot-color");
1268
+ this._defs.appendChild(this._dotsMask);
1271
1269
  this._createColor({
1272
1270
  options: options.dotsOptions?.gradient,
1273
1271
  color: options.dotsOptions.color,
@@ -1293,8 +1291,8 @@ class QRSVG {
1293
1291
  return false;
1294
1292
  return !!this._qr && this._qr.isDark(j + yOffset, i + xOffset);
1295
1293
  });
1296
- if (dot._element && this._dotsClipPath) {
1297
- this._dotsClipPath.appendChild(dot._element);
1294
+ if (dot._element && this._dotsMask) {
1295
+ this._dotsMaskGroup.appendChild(dot._element);
1298
1296
  }
1299
1297
  }
1300
1298
  }
@@ -1333,8 +1331,8 @@ class QRSVG {
1333
1331
  dot.draw(xFakeBeginning + i * dotSize, yFakeBeginning + j * dotSize, dotSize, (xOffset, yOffset) => {
1334
1332
  return !!fakeMatrix[i + xOffset]?.[j + yOffset];
1335
1333
  });
1336
- if (dot._element && this._dotsClipPath) {
1337
- this._dotsClipPath.appendChild(dot._element);
1334
+ if (dot._element && this._dotsMask) {
1335
+ this._dotsMaskGroup.appendChild(dot._element);
1338
1336
  }
1339
1337
  }
1340
1338
  }
@@ -1362,13 +1360,15 @@ class QRSVG {
1362
1360
  ].forEach(([column, row, rotation]) => {
1363
1361
  const x = xBeginning + column * dotSize * (count - 7);
1364
1362
  const y = yBeginning + row * dotSize * (count - 7);
1365
- let cornersSquareClipPath = this._dotsClipPath;
1366
- let cornersDotClipPath = this._dotsClipPath;
1363
+ let cornersSquareMask = this._dotsMask;
1364
+ let cornersSquareMaskGroup = this._dotsMaskGroup;
1365
+ let cornersDotMask = this._dotsMask;
1366
+ let cornersDotMaskGroup = this._dotsMaskGroup;
1367
1367
  if (options.cornersSquareOptions?.gradient || options.cornersSquareOptions?.color) {
1368
- cornersSquareClipPath = this._document.createElementNS("http://www.w3.org/2000/svg", "clipPath");
1369
- cornersSquareClipPath.setAttribute("id", `clip-path-corners-square-color-${column}-${row}`);
1370
- this._defs.appendChild(cornersSquareClipPath);
1371
- this._cornersSquareClipPath = this._cornersDotClipPath = cornersDotClipPath = cornersSquareClipPath;
1368
+ [cornersSquareMask, cornersSquareMaskGroup] = this._createMask(`mask-corners-square-color-${column}-${row}`);
1369
+ this._defs.appendChild(cornersSquareMask);
1370
+ this._cornersSquareMask = this._cornersDotMask = cornersDotMask = cornersSquareMask;
1371
+ this._cornersSquareMaskGroup = this._cornersDotMaskGroup = cornersDotMaskGroup = cornersSquareMaskGroup;
1372
1372
  this._createColor({
1373
1373
  options: options.cornersSquareOptions?.gradient,
1374
1374
  color: options.cornersSquareOptions?.color,
@@ -1387,8 +1387,8 @@ class QRSVG {
1387
1387
  document: this._document
1388
1388
  });
1389
1389
  cornersSquare.draw(x, y, cornersSquareSize, rotation);
1390
- if (cornersSquare._element && cornersSquareClipPath) {
1391
- cornersSquareClipPath.appendChild(cornersSquare._element);
1390
+ if (cornersSquare._element && cornersSquareMaskGroup) {
1391
+ cornersSquareMaskGroup.appendChild(cornersSquare._element);
1392
1392
  }
1393
1393
  }
1394
1394
  else {
@@ -1399,17 +1399,17 @@ class QRSVG {
1399
1399
  continue;
1400
1400
  }
1401
1401
  dot.draw(x + i * dotSize, y + j * dotSize, dotSize, (xOffset, yOffset) => !!squareMask[i + xOffset]?.[j + yOffset]);
1402
- if (dot._element && cornersSquareClipPath) {
1403
- cornersSquareClipPath.appendChild(dot._element);
1402
+ if (dot._element && cornersSquareMaskGroup) {
1403
+ cornersSquareMaskGroup.appendChild(dot._element);
1404
1404
  }
1405
1405
  }
1406
1406
  }
1407
1407
  }
1408
1408
  if (options.cornersDotOptions?.gradient || options.cornersDotOptions?.color) {
1409
- cornersDotClipPath = this._document.createElementNS("http://www.w3.org/2000/svg", "clipPath");
1410
- cornersDotClipPath.setAttribute("id", `clip-path-corners-dot-color-${column}-${row}`);
1411
- this._defs.appendChild(cornersDotClipPath);
1412
- this._cornersDotClipPath = cornersDotClipPath;
1409
+ [cornersDotMask, cornersDotMaskGroup] = this._createMask(`mask-corners-dot-color-${column}-${row}`);
1410
+ this._defs.appendChild(cornersDotMask);
1411
+ this._cornersDotMask = cornersDotMask;
1412
+ this._cornersDotMaskGroup = cornersDotMaskGroup;
1413
1413
  this._createColor({
1414
1414
  options: options.cornersDotOptions?.gradient,
1415
1415
  color: options.cornersDotOptions?.color,
@@ -1428,8 +1428,8 @@ class QRSVG {
1428
1428
  document: this._document
1429
1429
  });
1430
1430
  cornersDot.draw(x + dotSize * 2, y + dotSize * 2, cornersDotSize, rotation);
1431
- if (cornersDot._element && cornersDotClipPath) {
1432
- cornersDotClipPath.appendChild(cornersDot._element);
1431
+ if (cornersDot._element && cornersDotMaskGroup) {
1432
+ cornersDotMaskGroup.appendChild(cornersDot._element);
1433
1433
  }
1434
1434
  }
1435
1435
  else {
@@ -1440,8 +1440,8 @@ class QRSVG {
1440
1440
  continue;
1441
1441
  }
1442
1442
  dot.draw(x + i * dotSize, y + j * dotSize, dotSize, (xOffset, yOffset) => !!dotMask[i + xOffset]?.[j + yOffset]);
1443
- if (dot._element && cornersDotClipPath) {
1444
- cornersDotClipPath.appendChild(dot._element);
1443
+ if (dot._element && cornersDotMaskGroup) {
1444
+ cornersDotMaskGroup.appendChild(dot._element);
1445
1445
  }
1446
1446
  }
1447
1447
  }
@@ -1459,7 +1459,7 @@ class QRSVG {
1459
1459
  const dh = height - margin * 2;
1460
1460
  const imageUrl = await this._imageTools.toDataURL(options.image || "");
1461
1461
  let image = this._document.createElementNS("http://www.w3.org/2000/svg", "image");
1462
- image.setAttribute("href", imageUrl || "");
1462
+ image.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", imageUrl || "");
1463
1463
  if (imageUrl.startsWith("data:image/svg+xml;")) {
1464
1464
  let data = imageUrl.substring(19);
1465
1465
  const i = data.indexOf(",");
@@ -1494,7 +1494,7 @@ class QRSVG {
1494
1494
  rect.setAttribute("y", String(y));
1495
1495
  rect.setAttribute("height", String(height));
1496
1496
  rect.setAttribute("width", String(width));
1497
- rect.setAttribute("clip-path", `url('#clip-path-${name}')`);
1497
+ rect.setAttribute("style", `mask:url(#mask-${name})`);
1498
1498
  if (options) {
1499
1499
  let gradient;
1500
1500
  if (options.type === GradientType.radial) {
@@ -1553,7 +1553,7 @@ class QRSVG {
1553
1553
  stop.setAttribute("stop-color", color);
1554
1554
  gradient.appendChild(stop);
1555
1555
  });
1556
- rect.setAttribute("fill", `url('#${name}')`);
1556
+ rect.setAttribute("fill", `url(#${name})`);
1557
1557
  this._defs.appendChild(gradient);
1558
1558
  }
1559
1559
  else if (color) {
@@ -1561,6 +1561,20 @@ class QRSVG {
1561
1561
  }
1562
1562
  this._element.appendChild(rect);
1563
1563
  }
1564
+ _createMask(id) {
1565
+ const options = this._options;
1566
+ const mask = this._document.createElementNS("http://www.w3.org/2000/svg", "mask");
1567
+ mask.setAttribute("id", id);
1568
+ mask.setAttribute("maskUnits", "userSpaceOnUse");
1569
+ mask.setAttribute("x", "0");
1570
+ mask.setAttribute("y", "0");
1571
+ mask.setAttribute("width", String(options.width));
1572
+ mask.setAttribute("height", String(options.height));
1573
+ const group = this._document.createElementNS("http://www.w3.org/2000/svg", "g");
1574
+ group.setAttribute("fill", "#fff");
1575
+ mask.appendChild(group);
1576
+ return [mask, group];
1577
+ }
1564
1578
  }
1565
1579
 
1566
1580
  let QRCodeStyling$1 = class QRCodeStyling {