@liquid-js/qr-code-styling 5.6.1 → 5.7.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.
@@ -13,4 +13,13 @@ interface ImageSizeResult {
13
13
  hideXDots: number;
14
14
  }
15
15
  export declare function calculateImageSize({ originalHeight, originalWidth, maxHiddenDots, maxHiddenAxisDots, dotSize, margin }: ImageSizeOptions): ImageSizeResult;
16
+ /**
17
+ * Create an element drawing the image (a data URL) within the bounds; SVG images are embedded inline
18
+ */
19
+ export declare function createImageElement(document: Document, imageUrl: string, { x, y, width, height }: {
20
+ x: number;
21
+ y: number;
22
+ width: number;
23
+ height: number;
24
+ }): SVGElement;
16
25
  export {};
@@ -72,11 +72,56 @@ export declare enum ImageMode {
72
72
  */
73
73
  background = "background"
74
74
  }
75
+ export interface GeneratorMask {
76
+ /**
77
+ * Matrix indexed as mask[x][y]; false hides the segment at [x, y]
78
+ *
79
+ * The QR code occupies [startX, startX + count) × [startY, startY + count), with count as passed to
80
+ * Plugin.applyMask; it must lie inside the mask with the requested padding and its corners visible,
81
+ * or an error is thrown.
82
+ * Remaining segments are filled pseudo-randomly.
83
+ *
84
+ * With a mask, the shape is square and the QR code is drawn from [0, 0], with extra segments outside the
85
+ * viewBox. Options that extend the image size are ignored, except the image margin in ImageMode.background.
86
+ */
87
+ mask: boolean[][];
88
+ /** Mask column where the QR code starts */
89
+ startX: number;
90
+ /** Mask row where the QR code starts */
91
+ startY: number;
92
+ /**
93
+ * Center the gradient at the mask bounds instead of the QR code (scaled proportionally either way)
94
+ *
95
+ * @default false
96
+ */
97
+ fitGradient?: boolean;
98
+ }
99
+ /**
100
+ * Mask applied to the QR code, with its rendering data
101
+ */
102
+ export interface AppliedMask extends GeneratorMask {
103
+ /** QR code size in segments */
104
+ count: number;
105
+ /** Segment size */
106
+ dotSize: number;
107
+ /** Position of the mask's [0, 0] segment within the SVG */
108
+ x: number;
109
+ y: number;
110
+ }
75
111
  export interface Plugin {
76
112
  /**
77
113
  * Modify the options before rendering
78
114
  */
79
115
  configure?: (options: Options) => Options | undefined | void;
116
+ /**
117
+ * Add (or hide) QR code segments, e.g. to fit a QR code into a custom shape, the same way
118
+ * ShapeType.circle fits it inside a circle
119
+ *
120
+ * @param count QR code size in segments
121
+ * @param padding Mask rows and columns required on each side of the QR code (1 in ImageMode.background)
122
+ * @returns Segment mask; if undefined, try the next plugin or draw without a mask
123
+ */
124
+ applyMask?: (count: number, padding: number) => GeneratorMask | undefined | void;
80
125
  /**
81
126
  * Draw a single dot
82
127
  *
@@ -101,7 +146,7 @@ export interface Plugin {
101
146
  postProcess?: (svg: SVGSVGElement, options: Options, colors: {
102
147
  dots?: ColorElementValue;
103
148
  background?: ColorElementValue;
104
- }) => void;
149
+ }) => void | Promise<void>;
105
150
  }
106
151
  export interface Options {
107
152
  /** Use a custom DOM domplementation */
@@ -120,6 +165,8 @@ export interface Options {
120
165
  height: number;
121
166
  /** @ignore */
122
167
  size: number;
168
+ /** @ignore Mask applied to the QR code */
169
+ mask?: AppliedMask;
123
170
  /** The data will be encoded in the QR code */
124
171
  data: string;
125
172
  /** The image will be copied to the center of the QR code */
@@ -1,13 +1,43 @@
1
1
  import { RotateFigureArgs } from '../types/helper.js';
2
2
  export declare function numToAttr(value: number | string): string;
3
- export declare function svgPath(strings: TemplateStringsArray, ...values: unknown[]): string;
3
+ /**
4
+ * Template tag for SVG attribute values (path data, transforms, lengths, ...);
5
+ * formats interpolated numbers with numToAttr and collapses whitespace
6
+ */
7
+ export declare function svgAttr(strings: TemplateStringsArray, ...values: unknown[]): string;
8
+ /**
9
+ * @deprecated Use svgAttr
10
+ */
11
+ export declare const svgPath: typeof svgAttr;
4
12
  export declare function rotateFigure<T extends SVGElement | ReadonlyArray<SVGElement>>({ draw, ...args }: RotateFigureArgs<T>): T;
5
13
  export declare function scalePath(path: Array<string | number>, { x, y, size }: {
6
14
  x: number;
7
15
  y: number;
8
16
  size: number;
9
17
  }): string;
10
- export declare function extendSVG(svg: SVGSVGElement, padding: number): {
18
+ /**
19
+ * Parse path data into commands with numeric arguments; undefined if invalid
20
+ */
21
+ export declare function parsePath(d: string): [string, number[]][] | undefined;
22
+ /**
23
+ * Merge clip path shapes into a single path per clip rule, so the result can be drawn as a plain filled path
24
+ *
25
+ * @returns Path data grouped by clip rule, or undefined if any of the shapes can't be expressed as a path
26
+ */
27
+ export declare function mergeShapes(elements: Element[]): {
28
+ rule: string;
29
+ d: string;
30
+ }[] | undefined;
31
+ export interface SVGPadding {
32
+ left: number;
33
+ top: number;
34
+ right: number;
35
+ bottom: number;
36
+ }
37
+ /**
38
+ * Extend the SVG by a uniform (non-negative) padding, or by the given amount on each side
39
+ */
40
+ export declare function extendSVG(svg: SVGSVGElement, padding: number | Partial<SVGPadding>): {
11
41
  left: number;
12
42
  right: number;
13
43
  top: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liquid-js/qr-code-styling",
3
- "version": "5.6.1",
3
+ "version": "5.7.0-0",
4
4
  "description": "Generate styled QR codes on web or in Node",
5
5
  "type": "module",
6
6
  "main": "./lib/qr-code-styling-node.js",
@@ -35,6 +35,10 @@
35
35
  "types": "./lib/plugins/font-faces.d.ts",
36
36
  "default": "./lib/font-faces-plugin.js"
37
37
  },
38
+ "./image-mask-plugin": {
39
+ "types": "./lib/plugins/image-mask/index.d.ts",
40
+ "default": "./lib/image-mask-plugin.js"
41
+ },
38
42
  "./vcard-plugin": {
39
43
  "types": "./lib/plugins/vcard.d.ts",
40
44
  "default": "./lib/vcard-plugin.js"
@@ -88,8 +92,5 @@
88
92
  "bugs": {
89
93
  "url": "https://github.com/Liquid-JS/qr-code-styling/issues"
90
94
  },
91
- "homepage": "https://qrky.to/",
92
- "dependencies": {
93
- "tslib": "^2.8.1"
94
- }
95
+ "homepage": "https://qrky.to/"
95
96
  }
@@ -1,2 +0,0 @@
1
- import{numToAttr as t}from"./plugin-utils.js";var a,e=a||={};function r(t){var a=[],e=1;if("#"===(t=t.toLowerCase())[0]){let r=(t=t.slice(1)).length;r<=4?(a=[parseInt(t[0]+t[0],16),parseInt(t[1]+t[1],16),parseInt(t[2]+t[2],16)],4===r&&(e=parseInt(t[3]+t[3],16)/255)):(a=[parseInt(t[0]+t[1],16),parseInt(t[2]+t[3],16),parseInt(t[4]+t[5],16)],8===r&&(e=parseInt(t[6]+t[7],16)/255)),a[0]||(a[0]=0),a[1]||(a[1]=0),a[2]||(a[2]=0)}else{if(!(a=/^((?:rgba?))\s*\(([^)]*)\)/.exec(t)))return{value:t,alpha:e};e=(a=(a=a[2].trim().split(/\s*[,/]\s*|\s+/)).map((t,a)=>"%"===t[t.length-1]?(t=parseFloat(t)/100,3===a?t:255*t):"none"===t?0:parseFloat(t))).length>3?a.pop():1}return{value:"#"+a.map(t=>Math.max(0,Math.min(255,t)).toString(16).padStart(2,"0")).join(""),alpha:Math.max(0,Math.min(1,e))}}function i({options:e,color:i,additionalRotation:o,x:n,y:s,height:l,width:p,name:h,dotSize:u,document:c}){var M=p>l?p:l;if(n-=u,s-=u,p+=2*u,l+=2*u,e){let d;return e.type===a.radial?(d=c.createElementNS("http://www.w3.org/2000/svg","radialGradient"),d.setAttribute("id",h),d.setAttribute("gradientUnits","userSpaceOnUse"),d.setAttribute("fx",t(n+p/2)),d.setAttribute("fy",t(s+l/2)),d.setAttribute("cx",t(n+p/2)),d.setAttribute("cy",t(s+l/2)),d.setAttribute("r",t(M/2))):(u=n+p/2,M=s+l/2,n+=p/2,s+=l/2,(o=((i=((e.rotation||0)+o)%(2*Math.PI))+2*Math.PI)%(2*Math.PI))>=0&&o<=.25*Math.PI||o>1.75*Math.PI&&o<=2*Math.PI?(u-=p/2,M-=l/2*Math.tan(i),n+=p/2,s+=l/2*Math.tan(i)):o>.25*Math.PI&&o<=.75*Math.PI?(M-=l/2,u-=p/2/Math.tan(i),s+=l/2,n+=p/2/Math.tan(i)):o>.75*Math.PI&&o<=1.25*Math.PI?(u+=p/2,M+=l/2*Math.tan(i),n-=p/2,s-=l/2*Math.tan(i)):o>1.25*Math.PI&&o<=1.75*Math.PI&&(M+=l/2,u+=p/2/Math.tan(i),s-=l/2,n-=p/2/Math.tan(i)),d=c.createElementNS("http://www.w3.org/2000/svg","linearGradient"),d.setAttribute("id",h),d.setAttribute("gradientUnits","userSpaceOnUse"),d.setAttribute("x1",t(u)),d.setAttribute("y1",t(M)),d.setAttribute("x2",t(n)),d.setAttribute("y2",t(s))),e.colorStops.forEach(a=>{var e=c.createElementNS("http://www.w3.org/2000/svg","stop");e.setAttribute("offset",`${t(100*a.offset)}%`),a=r(a.color),e.setAttribute("stop-color",a.value),a.alpha<1&&e.setAttribute("stop-opacity",a.alpha.toFixed(7)),d.appendChild(e)}),{gradient:d,value:`url(#${h})`,opacity:1}}if(i)return{value:(e=r(i)).value,opacity:e.alpha}}function o(t){if(!(t={...t}).colorStops||!t.colorStops.length)throw Error("Field 'colorStops' is required in gradient");return t.rotation=t.rotation?Number(t.rotation):0,t.colorStops=t.colorStops.map(t=>({...t,offset:Number(t.offset)})),t}e.radial="radial",e.linear="linear";export{a as G,i as c,o as s};
2
- //# sourceMappingURL=color-dXYWdVDW.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"color-dXYWdVDW.js","sources":["../src/utils/gradient.ts","../src/utils/color.ts"],"sourcesContent":["export enum GradientType {\r\n radial = 'radial',\r\n linear = 'linear'\r\n}\r\n\r\nexport interface Gradient {\r\n /**\r\n * Type of gradient spread\r\n *\r\n * @default GradientType.linear\r\n */\r\n type: `${GradientType}`\r\n /**\r\n * Rotation of gradient (in radians, Math.PI === 180 degrees)\r\n *\r\n * @default 0\r\n */\r\n rotation?: number\r\n /** Gradient colors. */\r\n colorStops: Array<{\r\n /** Position of color in gradient range */\r\n offset: number\r\n /** Color of stop in gradient range */\r\n color: string\r\n }>\r\n}\r\n\r\nexport function sanitizeGradient(gradient: Gradient): Gradient {\r\n const newGradient = { ...gradient }\r\n\r\n if (!newGradient.colorStops || !newGradient.colorStops.length) {\r\n throw new Error(\"Field 'colorStops' is required in gradient\")\r\n }\r\n\r\n if (newGradient.rotation) {\r\n newGradient.rotation = Number(newGradient.rotation)\r\n } else {\r\n newGradient.rotation = 0\r\n }\r\n\r\n newGradient.colorStops = newGradient.colorStops.map((colorStop: { offset: number, color: string }) => ({\r\n ...colorStop,\r\n offset: Number(colorStop.offset)\r\n }))\r\n\r\n return newGradient\r\n}\r\n","import { Gradient, GradientType } from './gradient.js'\r\nimport { numToAttr } from './svg.js'\r\n\r\nexport function parseColor(cstr: string) {\r\n let m: RegExpExecArray | null\r\n let parts: string[] | number[] = []\r\n let alpha = 1\r\n\r\n cstr = cstr.toLowerCase()\r\n\r\n if (cstr[0] === '#') {\r\n const base = cstr.slice(1)\r\n const size = base.length\r\n const isShort = size <= 4\r\n\r\n if (isShort) {\r\n parts = [parseInt(base[0] + base[0], 16), parseInt(base[1] + base[1], 16), parseInt(base[2] + base[2], 16)]\r\n if (size === 4) {\r\n alpha = parseInt(base[3] + base[3], 16) / 255\r\n }\r\n } else {\r\n parts = [parseInt(base[0] + base[1], 16), parseInt(base[2] + base[3], 16), parseInt(base[4] + base[5], 16)]\r\n if (size === 8) {\r\n alpha = parseInt(base[6] + base[7], 16) / 255\r\n }\r\n }\r\n\r\n if (!parts[0]) parts[0] = 0\r\n if (!parts[1]) parts[1] = 0\r\n if (!parts[2]) parts[2] = 0\r\n } else if ((m = /^((?:rgba?))\\s*\\(([^)]*)\\)/.exec(cstr))) {\r\n const dims = 3\r\n parts = m[2].trim().split(/\\s*[,/]\\s*|\\s+/)\r\n\r\n parts = parts.map((x, i) => {\r\n if (x[x.length - 1] === '%') {\r\n const v = parseFloat(x) / 100\r\n if (i === 3) return v\r\n return v * 255\r\n }\r\n\r\n if (x === 'none') return 0\r\n return parseFloat(x)\r\n })\r\n\r\n alpha = parts.length > dims ? parts.pop()! : 1\r\n } else {\r\n return {\r\n value: cstr,\r\n alpha\r\n }\r\n }\r\n\r\n const value = '#' + parts.map((v) => Math.max(0, Math.min(255, v)).toString(16).padStart(2, '0')).join('')\r\n return {\r\n value,\r\n alpha: Math.max(0, Math.min(1, alpha))\r\n }\r\n}\r\n\r\nexport interface ColorElementValue {\r\n gradient?: SVGElement\r\n value: string\r\n opacity: number\r\n}\r\n\r\nexport function createColor({\r\n options,\r\n color,\r\n additionalRotation,\r\n x,\r\n y,\r\n height,\r\n width,\r\n name,\r\n dotSize: size,\r\n document\r\n}: {\r\n options?: Gradient\r\n color?: string\r\n additionalRotation: number\r\n x: number\r\n y: number\r\n height: number\r\n width: number\r\n name: string\r\n dotSize: number\r\n document: Document\r\n}): ColorElementValue | undefined {\r\n const gradientSize = width > height ? width : height\r\n\r\n x -= size\r\n y -= size\r\n width += 2 * size\r\n height += 2 * size\r\n\r\n if (options) {\r\n let gradient: SVGElement\r\n if (options.type === GradientType.radial) {\r\n gradient = document.createElementNS('http://www.w3.org/2000/svg', 'radialGradient')\r\n gradient.setAttribute('id', name)\r\n gradient.setAttribute('gradientUnits', 'userSpaceOnUse')\r\n gradient.setAttribute('fx', numToAttr(x + width / 2))\r\n gradient.setAttribute('fy', numToAttr(y + height / 2))\r\n gradient.setAttribute('cx', numToAttr(x + width / 2))\r\n gradient.setAttribute('cy', numToAttr(y + height / 2))\r\n gradient.setAttribute('r', numToAttr(gradientSize / 2))\r\n } else {\r\n const rotation = ((options.rotation || 0) + additionalRotation) % (2 * Math.PI)\r\n const positiveRotation = (rotation + 2 * Math.PI) % (2 * Math.PI)\r\n let x0 = x + width / 2\r\n let y0 = y + height / 2\r\n let x1 = x + width / 2\r\n let y1 = y + height / 2\r\n\r\n if (\r\n (positiveRotation >= 0 && positiveRotation <= 0.25 * Math.PI) ||\r\n (positiveRotation > 1.75 * Math.PI && positiveRotation <= 2 * Math.PI)\r\n ) {\r\n x0 = x0 - width / 2\r\n y0 = y0 - (height / 2) * Math.tan(rotation)\r\n x1 = x1 + width / 2\r\n y1 = y1 + (height / 2) * Math.tan(rotation)\r\n } else if (positiveRotation > 0.25 * Math.PI && positiveRotation <= 0.75 * Math.PI) {\r\n y0 = y0 - height / 2\r\n x0 = x0 - width / 2 / Math.tan(rotation)\r\n y1 = y1 + height / 2\r\n x1 = x1 + width / 2 / Math.tan(rotation)\r\n } else if (positiveRotation > 0.75 * Math.PI && positiveRotation <= 1.25 * Math.PI) {\r\n x0 = x0 + width / 2\r\n y0 = y0 + (height / 2) * Math.tan(rotation)\r\n x1 = x1 - width / 2\r\n y1 = y1 - (height / 2) * Math.tan(rotation)\r\n } else if (positiveRotation > 1.25 * Math.PI && positiveRotation <= 1.75 * Math.PI) {\r\n y0 = y0 + height / 2\r\n x0 = x0 + width / 2 / Math.tan(rotation)\r\n y1 = y1 - height / 2\r\n x1 = x1 - width / 2 / Math.tan(rotation)\r\n }\r\n\r\n gradient = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient')\r\n gradient.setAttribute('id', name)\r\n gradient.setAttribute('gradientUnits', 'userSpaceOnUse')\r\n gradient.setAttribute('x1', numToAttr(x0))\r\n gradient.setAttribute('y1', numToAttr(y0))\r\n gradient.setAttribute('x2', numToAttr(x1))\r\n gradient.setAttribute('y2', numToAttr(y1))\r\n }\r\n\r\n options.colorStops.forEach((stopCfg: { offset: number, color: string }) => {\r\n const stop = document.createElementNS('http://www.w3.org/2000/svg', 'stop')\r\n stop.setAttribute('offset', `${numToAttr(100 * stopCfg.offset)}%`)\r\n\r\n const parsed = parseColor(stopCfg.color)\r\n stop.setAttribute('stop-color', parsed.value)\r\n if (parsed.alpha < 1) stop.setAttribute('stop-opacity', parsed.alpha.toFixed(7))\r\n gradient.appendChild(stop)\r\n })\r\n\r\n return {\r\n gradient,\r\n value: `url(#${name})`,\r\n opacity: 1\r\n }\r\n } else if (color) {\r\n const parsed = parseColor(color)\r\n\r\n return {\r\n value: parsed.value,\r\n opacity: parsed.alpha\r\n }\r\n }\r\n return\r\n}\r\n"],"names":["numToAttr","p","t","parseColor","cstr","parts","alpha","toLowerCase","size","base","slice","length","parseInt","m","exec","value","trim","split","map","x","i","v","parseFloat","dims","pop","Math","max","min","toString","padStart","join","createColor","a","color","b","additionalRotation","h","f","width","g","name","dotSize","k","document","r","l","gradientSize","height","c","options","type","radial","e","setAttribute","x0","y0","y","rotation","PI","positiveRotation","tan","x1","y1","gradient","createElementNS","colorStops","forEach","stopCfg","stop","offset","parsed","toFixed","appendChild","opacity","sanitizeGradient","Error","Number"],"mappings":"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"}