@liquid-js/qr-code-styling 5.0.3 → 5.2.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/README.md CHANGED
@@ -84,6 +84,7 @@ While the old API only supports a single extension, it is now possible to apply
84
84
 
85
85
  ```ts
86
86
  import BorderPlugin from '@liquid-js/qr-code-styling/border-plugin'
87
+ import FontFacesPlugin from '@liquid-js/qr-code-styling/font-faces-plugin'
87
88
 
88
89
  const qrCode = new QRCodeStyling({
89
90
  plugins: [
@@ -107,7 +108,17 @@ const qrCode = new QRCodeStyling({
107
108
  content: 'QR code'.toUpperCase()
108
109
  }
109
110
  }
110
- })
111
+ }),
112
+ /**
113
+ * Embed fonts used with BorderPlugin
114
+ *
115
+ * Not needed when using standard or local fonts, but recommended for portability and consistency; use
116
+ * subsetting if possible to reduce the generated file size.
117
+ */
118
+ new FontFacesPlugin([{
119
+ font: 'sans-serif',
120
+ src: `url(data:font/otf;base64,d09GMgABAA...)`
121
+ }])
111
122
  ]
112
123
  // ...other options
113
124
  })
@@ -1,2 +1,2 @@
1
- let t=/\.?0+$/;function e(e){return"string"==typeof e?e:e.toFixed(7).replace(t,"")}function i(t,...i){return t.reduce((t,r,s)=>{let o="";return s&&(o=i[s-1]),"number"==typeof o&&(o=e(o)),`${t}${o}${r}`},"").trim().replace(/[\s\n\r]+/gim," ")}var r,s=r||={};s.top="top",s.bottom="bottom",s.left="left",s.right="right";export default class{pluginOptions;idSuffix;constructor(t,e=Math.random().toFixed(10).substring(2)){this.pluginOptions=t,this.idSuffix=e}postProcess(t,s){let{document:o}=s;var n=this.pluginOptions.size;let $=function(t,i){i=Math.max(i,0),t.setAttribute("width",e(parseFloat(t.getAttribute("width")||"0")+2*i)),t.setAttribute("height",e(parseFloat(t.getAttribute("height")||"0")+2*i));let r=(t.getAttribute("viewBox")||"").split(" ").map((t,e)=>parseFloat(t)+(e<2?-1:2)*i);if(t.setAttribute("viewBox",r.map(e).join(" ")),!(r.length<4))return{left:r[0],right:r[2]+r[0],top:r[1],bottom:r[3]+r[1]}}(t,n+(this.pluginOptions.margin||0));if($){n=Math.abs(n);var a=($.left+$.right)/2,h=($.top+$.bottom)/2,p=Math.min(s.width,s.height)/2*(1-(this.pluginOptions.round||0)),l=Math.min($.right-$.left-2*n,$.bottom-$.top-2*n)/2-p+n/2,u=this.pluginOptions.round?l:0,g=this.pluginOptions.round?p:p+l;(s=o.createElementNS("http://www.w3.org/2000/svg","rect")).setAttribute("width",e(2*(g+u))),s.setAttribute("height",e(2*(g+u))),s.setAttribute("x",e(a-g-u)),s.setAttribute("y",e(h-g-u)),s.setAttribute("rx",e(u)),s.setAttribute("fill","none"),s.setAttribute("stroke",this.pluginOptions.color),s.setAttribute("stroke-width",e(n)),this.pluginOptions.dasharray&&s.setAttribute("stroke-dasharray",this.pluginOptions.dasharray),t.appendChild(s),[r.left,r.top,r.right,r.bottom].forEach(s=>{var n=this.pluginOptions.text,$=n?.[s];if($){let d=Array.from(t.childNodes).find(t=>"DEFS"==t.tagName.toUpperCase());d||(d=o.createElementNS("http://www.w3.org/2000/svg","defs"),t.appendChild(d));let f=o.createElementNS("http://www.w3.org/2000/svg","path"),w=$.size||n.size||1;switch(u=this.pluginOptions.round?l-w/3:0,g=this.pluginOptions.round?p:p+(l-w/3),s){case r.top:f.setAttribute("d",i`M ${a} ${h+u+g} h ${-g} a ${u} ${u} 0 0 1 ${-u} ${-u} v ${-2*g} a ${u} ${u} 0 0 1 ${u} ${-u} h ${2*g} a ${u} ${u} 0 0 1 ${u} ${u} v ${2*g} a ${u} ${u} 0 0 1 ${-u} ${u} h ${-g}`);break;case r.bottom:this.pluginOptions.round?u+=2*w/3:g+=2*w/3,f.setAttribute("d",i`M ${a} ${h-u-g} h ${-g} a ${u} ${u} 0 0 0 ${-u} ${u} v ${2*g} a ${u} ${u} 0 0 0 ${u} ${u} h ${2*g} a ${u} ${u} 0 0 0 ${u} ${-u} v ${-2*g} a ${u} ${u} 0 0 0 ${-u} ${-u} h ${-g}`);break;case r.left:f.setAttribute("d",i`M ${a+u+g} ${h} v ${g} a ${u} ${u} 0 0 1 ${-u} ${u} h ${-2*g} a ${u} ${u} 0 0 1 ${-u} ${-u} v ${-2*g} a ${u} ${u} 0 0 1 ${u} ${-u} h ${2*g} a ${u} ${u} 0 0 1 ${u} ${u} v ${g}`);break;case r.right:f.setAttribute("d",i`M ${a-u-g} ${h} v ${-g} a ${u} ${u} 0 0 1 ${u} ${-u} h ${2*g} a ${u} ${u} 0 0 1 ${u} ${u} v ${2*g} a ${u} ${u} 0 0 1 ${-u} ${u} h ${-2*g} a ${u} ${u} 0 0 1 ${-u} ${-u} v ${-g}`)}s=`border-text-${s}-${this.idSuffix}`,f.setAttribute("id",s),f.setAttribute("fill","none");let b=o.createElementNS("http://www.w3.org/2000/svg","tspan");b.setAttribute("font-family",$.font||n.font||"sans-serif"),b.setAttribute("fill",$.color||n.color||"#000"),b.setAttribute("font-weight",e($.fontWeight||n.fontWeight||"normal")),b.setAttribute("font-style",$.fontStyle||n.fontStyle||"normal"),b.setAttribute("font-size",e(w)),b.textContent=$.content,(n=o.createElementNS("http://www.w3.org/2000/svg","textPath")).setAttributeNS("http://www.w3.org/1999/xlink","xlink:href","#"+s),n.setAttribute("startOffset","50%"),n.setAttribute("text-anchor","middle"),n.appendChild(b),($=o.createElementNS("http://www.w3.org/2000/svg","text")).appendChild(n),d.appendChild(f),t.appendChild($)}}),this.pluginOptions.fontFaces&&((n=Array.from(t.childNodes).find(t=>"DEFS"==t.tagName.toUpperCase()))||(n=o.createElementNS("http://www.w3.org/2000/svg","defs"),t.appendChild(n)),(s=o.createElementNS("http://www.w3.org/2000/svg","style")).textContent=this.pluginOptions.fontFaces,n.appendChild(s))}}}
1
+ import{extendSVG as t,numToAttr as e,svgPath as i}from"./plugin-utils.js";var s,r=s||={};r.top="top",r.bottom="bottom",r.left="left",r.right="right";export default class{pluginOptions;idSuffix;constructor(t,e=Math.random().toFixed(10).substring(2)){this.pluginOptions=t,this.idSuffix=e}postProcess(r,o){let{document:n}=o,$=this.pluginOptions.proportional?o.size:1;var a=this.pluginOptions.size*$;let p=t(r,a+(this.pluginOptions.margin||0)*$);if(p){a=Math.abs(a);var h=(p.left+p.right)/2,l=(p.top+p.bottom)/2,u=o.size/2*(1-(this.pluginOptions.round||0)),d=Math.min(p.right-p.left-2*a,p.bottom-p.top-2*a)/2-u+a/2,g=this.pluginOptions.round?d:0,f=this.pluginOptions.round?u:u+d;(o=n.createElementNS("http://www.w3.org/2000/svg","rect")).setAttribute("width",e(2*(f+g))),o.setAttribute("height",e(2*(f+g))),o.setAttribute("x",e(h-f-g)),o.setAttribute("y",e(l-f-g)),o.setAttribute("rx",e(g)),o.setAttribute("fill","none"),o.setAttribute("stroke",this.pluginOptions.color),o.setAttribute("stroke-width",e(a)),this.pluginOptions.dasharray&&o.setAttribute("stroke-dasharray",this.pluginOptions.dasharray),r.appendChild(o),[s.left,s.top,s.right,s.bottom].forEach(t=>{var o=this.pluginOptions.text,a=o?.[t];if(a){let p=Array.from(r.childNodes).find(t=>"DEFS"==t.tagName.toUpperCase());p||(p=n.createElementNS("http://www.w3.org/2000/svg","defs"),r.appendChild(p));let w=n.createElementNS("http://www.w3.org/2000/svg","path"),b=(a.size||o.size||1)*$;switch(g=this.pluginOptions.round?d-b/3:0,f=this.pluginOptions.round?u:u+(d-b/3),t){case s.top:w.setAttribute("d",i`M ${h} ${l+g+f} h ${-f} a ${g} ${g} 0 0 1 ${-g} ${-g} v ${-2*f} a ${g} ${g} 0 0 1 ${g} ${-g} h ${2*f} a ${g} ${g} 0 0 1 ${g} ${g} v ${2*f} a ${g} ${g} 0 0 1 ${-g} ${g} h ${-f}`);break;case s.bottom:this.pluginOptions.round?g+=2*b/3:f+=2*b/3,w.setAttribute("d",i`M ${h} ${l-g-f} h ${-f} a ${g} ${g} 0 0 0 ${-g} ${g} v ${2*f} a ${g} ${g} 0 0 0 ${g} ${g} h ${2*f} a ${g} ${g} 0 0 0 ${g} ${-g} v ${-2*f} a ${g} ${g} 0 0 0 ${-g} ${-g} h ${-f}`);break;case s.left:w.setAttribute("d",i`M ${h+g+f} ${l} v ${f} a ${g} ${g} 0 0 1 ${-g} ${g} h ${-2*f} a ${g} ${g} 0 0 1 ${-g} ${-g} v ${-2*f} a ${g} ${g} 0 0 1 ${g} ${-g} h ${2*f} a ${g} ${g} 0 0 1 ${g} ${g} v ${f}`);break;case s.right:w.setAttribute("d",i`M ${h-g-f} ${l} v ${-f} a ${g} ${g} 0 0 1 ${g} ${-g} h ${2*f} a ${g} ${g} 0 0 1 ${g} ${g} v ${2*f} a ${g} ${g} 0 0 1 ${-g} ${g} h ${-2*f} a ${g} ${g} 0 0 1 ${-g} ${-g} v ${-f}`)}t=`border-text-${t}-${this.idSuffix}`,w.setAttribute("id",t),w.setAttribute("fill","none");let c=n.createElementNS("http://www.w3.org/2000/svg","tspan");c.setAttribute("font-family",a.font||o.font||"sans-serif"),c.setAttribute("fill",a.color||o.color||"#000"),c.setAttribute("font-weight",e(a.fontWeight||o.fontWeight||"normal")),c.setAttribute("font-style",a.fontStyle||o.fontStyle||"normal"),c.setAttribute("font-size",e(b)),c.textContent=a.content,(o=n.createElementNS("http://www.w3.org/2000/svg","textPath")).setAttributeNS("http://www.w3.org/1999/xlink","xlink:href","#"+t),o.setAttribute("startOffset","50%"),o.setAttribute("text-anchor","middle"),o.appendChild(c),(a=n.createElementNS("http://www.w3.org/2000/svg","text")).appendChild(o),p.appendChild(w),r.appendChild(a)}}),this.pluginOptions.fontFaces&&((a=Array.from(r.childNodes).find(t=>"DEFS"==t.tagName.toUpperCase()))||(a=n.createElementNS("http://www.w3.org/2000/svg","defs"),r.appendChild(a)),(o=n.createElementNS("http://www.w3.org/2000/svg","style")).textContent=this.pluginOptions.fontFaces,a.appendChild(o))}}}
2
2
  //# sourceMappingURL=border-plugin.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"border-plugin.js","sources":["../src/utils/svg.ts","../src/plugins/border.ts"],"sourcesContent":["import { RotateFigureArgs } from '../types/helper.js'\r\n\r\nconst rx = /\\.?0+$/\r\n\r\nexport function numToAttr(value: number | string) {\r\n if (typeof value == 'string') return value\r\n return value.toFixed(7).replace(rx, '')\r\n}\r\n\r\nexport function svgPath(strings: TemplateStringsArray, ...values: unknown[]) {\r\n return strings\r\n .reduce((t, v, i) => {\r\n let p: unknown = ''\r\n if (i) p = values[i - 1]\r\n if (typeof p == 'number') p = numToAttr(p)\r\n return `${t}${p}${v}`\r\n }, '')\r\n .trim()\r\n .replace(/[\\s\\n\\r]+/gim, ' ')\r\n}\r\n\r\nexport function rotateFigure<T extends SVGElement | ReadonlyArray<SVGElement>>({ draw, ...args }: RotateFigureArgs<T>) {\r\n const { x, y, size, rotation = 0 } = args\r\n const cx = x + size / 2\r\n const cy = y + size / 2\r\n\r\n const element = draw(args)\r\n if (rotation) (Array.isArray(element) ? element : [element])\r\n .forEach(el => el.setAttribute('transform', `rotate(${numToAttr((180 * rotation) / Math.PI)},${cx},${cy})`))\r\n return element\r\n}\r\n\r\nexport function scalePath(path: Array<string | number>, { x, y, size }: {\r\n x: number\r\n y: number\r\n size: number\r\n}) {\r\n let move = false\r\n let i = 0\r\n return path\r\n .map((v) => {\r\n if (typeof v == 'string') {\r\n i = 0\r\n move = v.toUpperCase() == v\r\n return v\r\n }\r\n i++\r\n v = v * size\r\n if (move) {\r\n v += i % 2 == 1 ? x : y\r\n }\r\n return numToAttr(v)\r\n })\r\n .join(' ')\r\n}\r\n\r\nexport function extendSVG(svg: SVGSVGElement, padding: number) {\r\n padding = Math.max(padding, 0)\r\n svg.setAttribute('width', numToAttr(parseFloat(svg.getAttribute('width') || '0') + 2 * padding))\r\n svg.setAttribute('height', numToAttr(parseFloat(svg.getAttribute('height') || '0') + 2 * padding))\r\n const vb = (svg.getAttribute('viewBox') || '').split(' ').map((v, i) => parseFloat(v) + (i < 2 ? -1 : 2) * padding)\r\n svg.setAttribute('viewBox', vb.map(numToAttr).join(' '))\r\n if (vb.length < 4)\r\n return undefined\r\n return {\r\n left: vb[0],\r\n right: vb[2] + vb[0],\r\n top: vb[1],\r\n bottom: vb[3] + vb[1]\r\n }\r\n}\r\n","import { Options, Plugin } from '../utils/options.js'\r\nimport { extendSVG, numToAttr, svgPath } from './utils.js'\r\n\r\nenum TextPosition {\r\n top = 'top',\r\n bottom = 'bottom',\r\n left = 'left',\r\n right = 'right'\r\n}\r\n\r\nexport interface TextConfig {\r\n font?: string\r\n color?: string\r\n size?: number\r\n fontWeight?: 'normal' | 'bold' | number\r\n fontStyle?: 'normal' | 'italic' | 'oblique'\r\n}\r\n\r\nexport interface BorderPluginOptions {\r\n /** Border roundnes, from 0 (square) to 1 (circle) */\r\n round?: number\r\n size: number\r\n color: string\r\n dasharray?: string\r\n margin?: number\r\n text?: TextConfig & {\r\n [key in TextPosition]?: TextConfig & {\r\n content: string\r\n }\r\n }\r\n /** A string of embedded CSS @font-face rules */\r\n fontFaces?: string\r\n}\r\n\r\nexport default class BorderPlugin implements Plugin {\r\n\r\n constructor(\r\n private readonly pluginOptions: BorderPluginOptions,\r\n /** @ignore Create unique id for SVG elements to prevent naming collisions; specify your own if neccesary e.g. for testing */\r\n private readonly idSuffix = Math.random().toFixed(10).substring(2)\r\n ) { }\r\n\r\n postProcess(svg: SVGSVGElement, options: Options) {\r\n const { document } = options\r\n const margin = this.pluginOptions.margin || 0\r\n let thickness = this.pluginOptions.size\r\n const drawArea = extendSVG(svg, thickness + margin)\r\n if (!drawArea)\r\n return\r\n\r\n thickness = Math.abs(thickness)\r\n\r\n const cx = (drawArea.left + drawArea.right) / 2\r\n const cy = (drawArea.top + drawArea.bottom) / 2\r\n const lineSize = Math.min(options.width, options.height) / 2 * (1 - (this.pluginOptions.round || 0))\r\n const r = (Math.min(drawArea.right - drawArea.left - 2 * thickness, drawArea.bottom - drawArea.top - 2 * thickness) / 2) - lineSize + thickness / 2\r\n\r\n let pathR = this.pluginOptions.round ? r : 0\r\n let pathL = this.pluginOptions.round ? lineSize : lineSize + r\r\n\r\n const borderEl = document.createElementNS('http://www.w3.org/2000/svg', 'rect')\r\n borderEl.setAttribute('width', numToAttr((pathL + pathR) * 2))\r\n borderEl.setAttribute('height', numToAttr((pathL + pathR) * 2))\r\n borderEl.setAttribute('x', numToAttr(cx - pathL - pathR))\r\n borderEl.setAttribute('y', numToAttr(cy - pathL - pathR))\r\n borderEl.setAttribute('rx', numToAttr(pathR))\r\n borderEl.setAttribute('fill', 'none')\r\n borderEl.setAttribute('stroke', this.pluginOptions.color)\r\n borderEl.setAttribute('stroke-width', numToAttr(thickness))\r\n if (this.pluginOptions.dasharray) {\r\n borderEl.setAttribute('stroke-dasharray', this.pluginOptions.dasharray)\r\n }\r\n\r\n svg.appendChild(borderEl);\r\n\r\n [TextPosition.left, TextPosition.top, TextPosition.right, TextPosition.bottom].forEach(postion => {\r\n const textCfg = this.pluginOptions.text\r\n const config = textCfg?.[postion]\r\n if (config) {\r\n let defs = Array.from(svg.childNodes).find(v => (v as HTMLElement).tagName.toUpperCase() == 'DEFS')\r\n if (!defs) {\r\n defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs')\r\n svg.appendChild(defs)\r\n }\r\n const element = document.createElementNS('http://www.w3.org/2000/svg', 'path')\r\n const size = (config.size || textCfg.size || 1)\r\n pathR = this.pluginOptions.round ? r - size / 3 : 0\r\n pathL = this.pluginOptions.round ? lineSize : lineSize + (r - size / 3)\r\n switch (postion) {\r\n case TextPosition.top:\r\n element.setAttribute(\r\n 'd',\r\n svgPath`M ${cx} ${cy + pathR + pathL}\r\n h ${-pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${-pathR} ${-pathR}\r\n v ${-2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${pathR} ${-pathR}\r\n h ${2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${pathR} ${pathR}\r\n v ${2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${-pathR} ${pathR}\r\n h ${-pathL}`\r\n )\r\n break\r\n case TextPosition.bottom:\r\n if (this.pluginOptions.round)\r\n pathR += size * 2 / 3\r\n else\r\n pathL += size * 2 / 3\r\n element.setAttribute(\r\n 'd',\r\n svgPath`M ${cx} ${cy - pathR - pathL}\r\n h ${-pathL}\r\n a ${pathR} ${pathR} 0 0 0 ${-pathR} ${pathR}\r\n v ${2 * pathL}\r\n a ${pathR} ${pathR} 0 0 0 ${pathR} ${pathR}\r\n h ${2 * pathL}\r\n a ${pathR} ${pathR} 0 0 0 ${pathR} ${-pathR}\r\n v ${-2 * pathL}\r\n a ${pathR} ${pathR} 0 0 0 ${-pathR} ${-pathR}\r\n h ${-pathL}`\r\n )\r\n break\r\n case TextPosition.left:\r\n element.setAttribute(\r\n 'd',\r\n svgPath`M ${cx + pathR + pathL} ${cy}\r\n v ${pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${-pathR} ${pathR}\r\n h ${-2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${-pathR} ${-pathR}\r\n v ${-2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${pathR} ${-pathR}\r\n h ${2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${pathR} ${pathR}\r\n v ${pathL}`\r\n )\r\n break\r\n case TextPosition.right:\r\n element.setAttribute(\r\n 'd',\r\n svgPath`M ${cx - pathR - pathL} ${cy}\r\n v ${-pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${pathR} ${-pathR}\r\n h ${2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${pathR} ${pathR}\r\n v ${2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${-pathR} ${pathR}\r\n h ${-2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${-pathR} ${-pathR}\r\n v ${-pathL}`\r\n )\r\n break\r\n }\r\n const id = `border-text-${postion}-${this.idSuffix}`\r\n element.setAttribute('id', id)\r\n element.setAttribute('fill', 'none')\r\n\r\n const span = document.createElementNS('http://www.w3.org/2000/svg', 'tspan')\r\n span.setAttribute('font-family', config.font || textCfg.font || 'sans-serif')\r\n span.setAttribute('fill', config.color || textCfg.color || '#000')\r\n span.setAttribute('font-weight', numToAttr(config.fontWeight || textCfg.fontWeight || 'normal'))\r\n span.setAttribute('font-style', config.fontStyle || textCfg.fontStyle || 'normal')\r\n span.setAttribute('font-size', numToAttr(size))\r\n span.textContent = config.content\r\n\r\n const textPath = document.createElementNS('http://www.w3.org/2000/svg', 'textPath')\r\n textPath.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', '#' + id)\r\n textPath.setAttribute('startOffset', '50%')\r\n textPath.setAttribute('text-anchor', 'middle')\r\n textPath.appendChild(span)\r\n\r\n const text = document.createElementNS('http://www.w3.org/2000/svg', 'text')\r\n text.appendChild(textPath)\r\n\r\n defs.appendChild(element)\r\n svg.appendChild(text)\r\n }\r\n })\r\n\r\n if (this.pluginOptions.fontFaces) {\r\n let defs = Array.from(svg.childNodes).find(v => (v as HTMLElement).tagName.toUpperCase() == 'DEFS')\r\n if (!defs) {\r\n defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs')\r\n svg.appendChild(defs)\r\n }\r\n const style = document.createElementNS('http://www.w3.org/2000/svg', 'style')\r\n style.textContent = this.pluginOptions.fontFaces\r\n defs.appendChild(style)\r\n }\r\n }\r\n}\r\n"],"names":["rx","numToAttr","value","toFixed","replace","svgPath","strings","values","reduce","t","v","i","p","trim","TextPosition","B","top","bottom","left","right","pluginOptions","idSuffix","constructor","Math","random","substring","this","postProcess","svg","options","document","thickness","size","drawArea","extendSVG","padding","max","setAttribute","parseFloat","getAttribute","split","map","vb","join","length","margin","abs","cx","cy","lineSize","min","width","height","round","pathR","r","pathL","borderEl","createElementNS","color","dasharray","appendChild","forEach","postion","text","textCfg","config","defs","Array","from","childNodes","find","tagName","toUpperCase","element","id","span","font","fontWeight","fontStyle","textContent","content","textPath","setAttributeNS","fontFaces","style"],"mappings":"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"}
1
+ {"version":3,"file":"border-plugin.js","sources":["../src/plugins/border.ts"],"sourcesContent":["import { Options, Plugin } from '../utils/options.js'\r\nimport { extendSVG, numToAttr, svgPath } from './utils.js'\r\n\r\nenum TextPosition {\r\n top = 'top',\r\n bottom = 'bottom',\r\n left = 'left',\r\n right = 'right'\r\n}\r\n\r\nexport interface TextConfig {\r\n font?: string\r\n color?: string\r\n size?: number\r\n fontWeight?: 'normal' | 'bold' | number\r\n fontStyle?: 'normal' | 'italic' | 'oblique'\r\n}\r\n\r\nexport interface BorderPluginOptions {\r\n /** Border roundnes, from 0 (square) to 1 (circle) */\r\n round?: number\r\n size: number\r\n color: string\r\n dasharray?: string\r\n margin?: number\r\n /**\r\n * If true, all dimensions are proportional to the code size,\r\n * i.e. `size: 0.1` means the border thickness is 1/10 of the QR code size\r\n *\r\n * This is useful to keep the border visually consistent regardless of the amount of data\r\n *\r\n * Note: if using dasharray, use percentage values to maintain consistency\r\n */\r\n proportional?: boolean\r\n text?: TextConfig & {\r\n [key in TextPosition]?: TextConfig & {\r\n content: string\r\n }\r\n }\r\n /**\r\n * A string of embedded CSS @font-face rules\r\n *\r\n * @deprecated Use @liquid-js/qr-code-styling/font-faces-plugin\r\n */\r\n fontFaces?: string\r\n}\r\n\r\nexport default class BorderPlugin implements Plugin {\r\n\r\n constructor(\r\n private readonly pluginOptions: BorderPluginOptions,\r\n /** @ignore Create unique id for SVG elements to prevent naming collisions; specify your own if neccesary e.g. for testing */\r\n private readonly idSuffix = Math.random().toFixed(10).substring(2)\r\n ) { }\r\n\r\n postProcess(svg: SVGSVGElement, options: Options) {\r\n const { document } = options\r\n const sizeFactor = this.pluginOptions.proportional ? options.size : 1\r\n\r\n const margin = (this.pluginOptions.margin || 0) * sizeFactor\r\n let thickness = (this.pluginOptions.size) * sizeFactor\r\n const drawArea = extendSVG(svg, thickness + margin)\r\n if (!drawArea)\r\n return\r\n\r\n thickness = Math.abs(thickness)\r\n\r\n const cx = (drawArea.left + drawArea.right) / 2\r\n const cy = (drawArea.top + drawArea.bottom) / 2\r\n const lineSize = options.size / 2 * (1 - (this.pluginOptions.round || 0))\r\n const r = (Math.min(drawArea.right - drawArea.left - 2 * thickness, drawArea.bottom - drawArea.top - 2 * thickness) / 2) - lineSize + thickness / 2\r\n\r\n let pathR = this.pluginOptions.round ? r : 0\r\n let pathL = this.pluginOptions.round ? lineSize : lineSize + r\r\n\r\n const borderEl = document.createElementNS('http://www.w3.org/2000/svg', 'rect')\r\n borderEl.setAttribute('width', numToAttr((pathL + pathR) * 2))\r\n borderEl.setAttribute('height', numToAttr((pathL + pathR) * 2))\r\n borderEl.setAttribute('x', numToAttr(cx - pathL - pathR))\r\n borderEl.setAttribute('y', numToAttr(cy - pathL - pathR))\r\n borderEl.setAttribute('rx', numToAttr(pathR))\r\n borderEl.setAttribute('fill', 'none')\r\n borderEl.setAttribute('stroke', this.pluginOptions.color)\r\n borderEl.setAttribute('stroke-width', numToAttr(thickness))\r\n if (this.pluginOptions.dasharray) {\r\n borderEl.setAttribute('stroke-dasharray', this.pluginOptions.dasharray)\r\n }\r\n\r\n svg.appendChild(borderEl);\r\n\r\n [TextPosition.left, TextPosition.top, TextPosition.right, TextPosition.bottom].forEach(postion => {\r\n const textCfg = this.pluginOptions.text\r\n const config = textCfg?.[postion]\r\n if (config) {\r\n let defs = Array.from(svg.childNodes).find(v => (v as HTMLElement).tagName.toUpperCase() == 'DEFS')\r\n if (!defs) {\r\n defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs')\r\n svg.appendChild(defs)\r\n }\r\n const element = document.createElementNS('http://www.w3.org/2000/svg', 'path')\r\n const size = (config.size || textCfg.size || 1) * sizeFactor\r\n pathR = this.pluginOptions.round ? r - size / 3 : 0\r\n pathL = this.pluginOptions.round ? lineSize : lineSize + (r - size / 3)\r\n switch (postion) {\r\n case TextPosition.top:\r\n element.setAttribute(\r\n 'd',\r\n svgPath`M ${cx} ${cy + pathR + pathL}\r\n h ${-pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${-pathR} ${-pathR}\r\n v ${-2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${pathR} ${-pathR}\r\n h ${2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${pathR} ${pathR}\r\n v ${2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${-pathR} ${pathR}\r\n h ${-pathL}`\r\n )\r\n break\r\n case TextPosition.bottom:\r\n if (this.pluginOptions.round)\r\n pathR += size * 2 / 3\r\n else\r\n pathL += size * 2 / 3\r\n element.setAttribute(\r\n 'd',\r\n svgPath`M ${cx} ${cy - pathR - pathL}\r\n h ${-pathL}\r\n a ${pathR} ${pathR} 0 0 0 ${-pathR} ${pathR}\r\n v ${2 * pathL}\r\n a ${pathR} ${pathR} 0 0 0 ${pathR} ${pathR}\r\n h ${2 * pathL}\r\n a ${pathR} ${pathR} 0 0 0 ${pathR} ${-pathR}\r\n v ${-2 * pathL}\r\n a ${pathR} ${pathR} 0 0 0 ${-pathR} ${-pathR}\r\n h ${-pathL}`\r\n )\r\n break\r\n case TextPosition.left:\r\n element.setAttribute(\r\n 'd',\r\n svgPath`M ${cx + pathR + pathL} ${cy}\r\n v ${pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${-pathR} ${pathR}\r\n h ${-2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${-pathR} ${-pathR}\r\n v ${-2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${pathR} ${-pathR}\r\n h ${2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${pathR} ${pathR}\r\n v ${pathL}`\r\n )\r\n break\r\n case TextPosition.right:\r\n element.setAttribute(\r\n 'd',\r\n svgPath`M ${cx - pathR - pathL} ${cy}\r\n v ${-pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${pathR} ${-pathR}\r\n h ${2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${pathR} ${pathR}\r\n v ${2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${-pathR} ${pathR}\r\n h ${-2 * pathL}\r\n a ${pathR} ${pathR} 0 0 1 ${-pathR} ${-pathR}\r\n v ${-pathL}`\r\n )\r\n break\r\n }\r\n const id = `border-text-${postion}-${this.idSuffix}`\r\n element.setAttribute('id', id)\r\n element.setAttribute('fill', 'none')\r\n\r\n const span = document.createElementNS('http://www.w3.org/2000/svg', 'tspan')\r\n span.setAttribute('font-family', config.font || textCfg.font || 'sans-serif')\r\n span.setAttribute('fill', config.color || textCfg.color || '#000')\r\n span.setAttribute('font-weight', numToAttr(config.fontWeight || textCfg.fontWeight || 'normal'))\r\n span.setAttribute('font-style', config.fontStyle || textCfg.fontStyle || 'normal')\r\n span.setAttribute('font-size', numToAttr(size))\r\n span.textContent = config.content\r\n\r\n const textPath = document.createElementNS('http://www.w3.org/2000/svg', 'textPath')\r\n textPath.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', '#' + id)\r\n textPath.setAttribute('startOffset', '50%')\r\n textPath.setAttribute('text-anchor', 'middle')\r\n textPath.appendChild(span)\r\n\r\n const text = document.createElementNS('http://www.w3.org/2000/svg', 'text')\r\n text.appendChild(textPath)\r\n\r\n defs.appendChild(element)\r\n svg.appendChild(text)\r\n }\r\n })\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-deprecated\r\n if (this.pluginOptions.fontFaces) {\r\n let defs = Array.from(svg.childNodes).find(v => (v as HTMLElement).tagName.toUpperCase() == 'DEFS')\r\n if (!defs) {\r\n defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs')\r\n svg.appendChild(defs)\r\n }\r\n const style = document.createElementNS('http://www.w3.org/2000/svg', 'style')\r\n // eslint-disable-next-line @typescript-eslint/no-deprecated\r\n style.textContent = this.pluginOptions.fontFaces\r\n defs.appendChild(style)\r\n }\r\n }\r\n}\r\n"],"names":["extendSVG","numToAttr","TextPosition","g","v","top","bottom","left","right","pluginOptions","idSuffix","constructor","Math","random","toFixed","substring","this","postProcess","svg","options","document","sizeFactor","proportional","size","thickness","drawArea","margin","abs","cx","cy","round","min","lineSize","pathR","r","pathL","createElementNS","setAttribute","borderEl","color","dasharray","appendChild","forEach","postion","text","textCfg","config","defs","Array","from","childNodes","find","tagName","toUpperCase","element","svgPath","id","span","font","fontWeight","fontStyle","textContent","content","textPath","setAttributeNS","fontFaces","style"],"mappings":"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"}
@@ -7,15 +7,12 @@ export declare class QRSVG {
7
7
  get element(): SVGSVGElement;
8
8
  private defs;
9
9
  private backgroundMask?;
10
- private backgroundMaskGroup?;
11
10
  private dotsMask?;
12
- private dotsMaskGroup?;
13
11
  private lightDotsMask?;
14
- private lightDotsMaskGroup?;
15
12
  private qr?;
16
13
  private document;
17
14
  private imageTools;
18
- constructor(options: Pick<Options, 'width' | 'height' | 'document' | 'imageTools' | 'image' | 'imageOptions' | 'dotsOptions' | 'cornersDotOptions' | 'cornersSquareOptions' | 'backgroundOptions' | 'shape' | 'plugins'> & {
15
+ constructor(options: Pick<Options, 'width' | 'height' | 'size' | 'document' | 'imageTools' | 'image' | 'imageOptions' | 'dotsOptions' | 'cornersDotOptions' | 'cornersSquareOptions' | 'backgroundOptions' | 'shape' | 'plugins'> & {
19
16
  errorCorrectionPercent: number;
20
17
  });
21
18
  get width(): number;
@@ -0,0 +1,2 @@
1
+ export default class{fontFaces;constructor(t){this.fontFaces=t.map(t=>"string"==typeof t?t:`@font-face { font-family: ${JSON.stringify(t.font)}; src: ${t.src}; ${t.fontStyle?`font-style: ${t.fontStyle};`:""} ${t.fontWeight?`font-weight: ${t.fontWeight};`:""} }`).join("\n")}postProcess(t,e){let o=e.document;(e=Array.from(t.childNodes).find(t=>"DEFS"==t.tagName.toUpperCase()))||(e=o.createElementNS("http://www.w3.org/2000/svg","defs"),t.appendChild(e)),(t=o.createElementNS("http://www.w3.org/2000/svg","style")).textContent=this.fontFaces,e.appendChild(t)}}
2
+ //# sourceMappingURL=font-faces-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"font-faces-plugin.js","sources":["../src/plugins/font-faces.ts"],"sourcesContent":["import { Options, Plugin } from '../utils/options.js'\r\nimport { TextConfig } from './border.js'\r\n\r\nexport interface FontFace extends Pick<TextConfig, 'font' | 'fontWeight' | 'fontStyle'> {\r\n /**\r\n * Base64 encoded font, e.g. `url(data:font/otf;base64,...)`\r\n */\r\n src: string\r\n}\r\n\r\n/**\r\n * Embed font faces into the generated SVG\r\n *\r\n * Use as the last plugin when using BorderPlugin({ text: { ... } })\r\n * or other plugins that insert text.\r\n */\r\nexport default class FontFacesPlugin implements Plugin {\r\n private readonly fontFaces: string\r\n constructor(fontFaces: Array<FontFace | string>) {\r\n this.fontFaces = fontFaces.map(v => {\r\n if (typeof v == 'string')\r\n return v\r\n return `@font-face { font-family: ${JSON.stringify(v.font)}; src: ${v.src}; ${v.fontStyle ? `font-style: ${v.fontStyle};` : ''} ${v.fontWeight ? `font-weight: ${v.fontWeight};` : ''} }`\r\n }).join('\\n')\r\n }\r\n\r\n postProcess(svg: SVGSVGElement, options: Options) {\r\n const document = options.document\r\n let defs = Array.from(svg.childNodes).find(v => (v as HTMLElement).tagName.toUpperCase() == 'DEFS')\r\n if (!defs) {\r\n defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs')\r\n svg.appendChild(defs)\r\n }\r\n const style = document.createElementNS('http://www.w3.org/2000/svg', 'style')\r\n style.textContent = this.fontFaces\r\n defs.appendChild(style)\r\n }\r\n}\r\n"],"names":["fontFaces","constructor","this","map","v","JSON","stringify","font","src","fontStyle","fontWeight","join","postProcess","svg","options","document","defs","Array","from","childNodes","find","tagName","toUpperCase","createElementNS","appendChild","style","textContent"],"mappings":"eAgBc,MACOA,UACjBC,WAAAA,CAAYD,GACRE,KAAKF,UAAYA,EAAUG,IAAIC,GACX,iBAALA,EACAA,EACJ,6BAA6BC,KAAKC,UAAUF,EAAEG,eAAeH,EAAEI,QAAQJ,EAAEK,UAAY,eAAeL,EAAEK,aAAe,MAAML,EAAEM,WAAa,gBAAgBN,EAAEM,cAAgB,QACpLC,KAAK,KALmC,CAQ/CC,WAAAA,CAAYC,EAAoBC,GAC5B,IAAAC,EAAcD,EAAGC,UACbC,EAAOC,MAAMC,KAAKL,EAAIM,YAAYC,KAAKhB,GAAiD,QAA3CA,EAAkBiB,QAAQC,kBAEvEN,EAAOD,EAASQ,gBAAgB,6BAA8B,QAC9DV,EAAIW,YAAYR,KAEpBS,EAAWV,EAAGQ,6CAAqD,UAC7DG,YAAcxB,KAAKF,UACzBgB,EAAKQ,YAAYC,EAT2B"}
@@ -19,12 +19,25 @@ export interface BorderPluginOptions {
19
19
  color: string;
20
20
  dasharray?: string;
21
21
  margin?: number;
22
+ /**
23
+ * If true, all dimensions are proportional to the code size,
24
+ * i.e. `size: 0.1` means the border thickness is 1/10 of the QR code size
25
+ *
26
+ * This is useful to keep the border visually consistent regardless of the amount of data
27
+ *
28
+ * Note: if using dasharray, use percentage values to maintain consistency
29
+ */
30
+ proportional?: boolean;
22
31
  text?: TextConfig & {
23
32
  [key in TextPosition]?: TextConfig & {
24
33
  content: string;
25
34
  };
26
35
  };
27
- /** A string of embedded CSS @font-face rules */
36
+ /**
37
+ * A string of embedded CSS @font-face rules
38
+ *
39
+ * @deprecated Use @liquid-js/qr-code-styling/font-faces-plugin
40
+ */
28
41
  fontFaces?: string;
29
42
  }
30
43
  export default class BorderPlugin implements Plugin {
@@ -0,0 +1,19 @@
1
+ import { Options, Plugin } from '../utils/options.js';
2
+ import { TextConfig } from './border.js';
3
+ export interface FontFace extends Pick<TextConfig, 'font' | 'fontWeight' | 'fontStyle'> {
4
+ /**
5
+ * Base64 encoded font, e.g. `url(data:font/otf;base64,...)`
6
+ */
7
+ src: string;
8
+ }
9
+ /**
10
+ * Embed font faces into the generated SVG
11
+ *
12
+ * Use as the last plugin when using BorderPlugin({ text: { ... } })
13
+ * or other plugins that insert text.
14
+ */
15
+ export default class FontFacesPlugin implements Plugin {
16
+ private readonly fontFaces;
17
+ constructor(fontFaces: Array<FontFace | string>);
18
+ postProcess(svg: SVGSVGElement, options: Options): void;
19
+ }
@@ -72,6 +72,7 @@ let defaultOptions = {
72
72
  shape: ShapeType.square,
73
73
  width: void 0,
74
74
  height: void 0,
75
+ size: void 0,
75
76
  data: "",
76
77
  qrOptions: {
77
78
  typeNumber: TypeNumber[0],
@@ -683,26 +684,23 @@ class QRSVG {
683
684
  }
684
685
  defs;
685
686
  backgroundMask;
686
- backgroundMaskGroup;
687
687
  dotsMask;
688
- dotsMaskGroup;
689
688
  lightDotsMask;
690
- lightDotsMaskGroup;
691
689
  qr;
692
690
  document;
693
691
  imageTools;
694
692
  constructor(options) {
695
693
  this.options = options, this.document = options.document, this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "svg");
696
- let width = numToAttr(options.width), height = numToAttr(options.height);
697
- this._element.setAttribute("width", width), this._element.setAttribute("height", height),
698
- this._element.setAttribute("viewBox", `0 0 ${width} ${height}`), this.defs = this.document.createElementNS("http://www.w3.org/2000/svg", "defs"),
694
+ let size = numToAttr(options.size);
695
+ this._element.setAttribute("width", size), this._element.setAttribute("height", size),
696
+ this._element.setAttribute("viewBox", `0 0 ${size} ${size}`), this.defs = this.document.createElementNS("http://www.w3.org/2000/svg", "defs"),
699
697
  this._element.appendChild(this.defs), this.imageTools = options.imageTools || browserImageTools;
700
698
  }
701
699
  get width() {
702
- return this.options.width;
700
+ return this.options.size;
703
701
  }
704
702
  get height() {
705
- return this.options.height;
703
+ return this.options.size;
706
704
  }
707
705
  async drawQR(qr) {
708
706
  let count = qr.getModuleCount(), typeNumber = parseInt(((count - 17) / 4).toFixed(0), 10), dotSize = this.options.dotsOptions.size, drawImageSize = {
@@ -714,9 +712,9 @@ class QRSVG {
714
712
  if (this.qr = qr, this.options.image) {
715
713
  let size = await this.imageTools.getSize(this.options.image, this.options.imageOptions.crossOrigin), {imageOptions, errorCorrectionPercent} = this.options;
716
714
  if (imageOptions.mode == ImageMode.background) {
717
- let margin = this.options.backgroundOptions && this.options.backgroundOptions.margin || 0, maxWidth = (this.options.width - 2 * margin * dotSize) * imageOptions.imageSize, maxHeight = (this.options.height - 2 * margin * dotSize) * imageOptions.imageSize, {width, height} = size;
718
- height = height / width * maxWidth, width = maxWidth, height > maxHeight && (width = width / height * maxHeight,
719
- height = maxHeight), drawImageSize = {
715
+ let margin = this.options.backgroundOptions && this.options.backgroundOptions.margin || 0, maxSize = (this.options.size - 2 * margin * dotSize) * imageOptions.imageSize, {width, height} = size;
716
+ height = height / width * maxSize, width = maxSize, height > maxSize && (width = width / height * maxSize,
717
+ height = maxSize), drawImageSize = {
720
718
  hideXDots: 0,
721
719
  hideYDots: 0,
722
720
  width,
@@ -793,33 +791,33 @@ class QRSVG {
793
791
  additionalRotation: 0,
794
792
  x: 0,
795
793
  y: 0,
796
- height: options.height,
797
- width: options.width,
794
+ height: options.size,
795
+ width: options.size,
798
796
  name: "background-color"
799
797
  });
800
- let size = Math.min(options.width, options.height), element = this.document.createElementNS("http://www.w3.org/2000/svg", "rect");
801
- [this.backgroundMask, this.backgroundMaskGroup] = this.createMask("mask-background-color"),
802
- this.defs.appendChild(this.backgroundMask), element.setAttribute("x", numToAttr((options.width - size) / 2)),
803
- element.setAttribute("y", numToAttr((options.height - size) / 2)), element.setAttribute("width", numToAttr(size)),
804
- element.setAttribute("height", numToAttr(size)), element.setAttribute("rx", numToAttr(size / 2 * (options.backgroundOptions.round || 0))),
805
- this.backgroundMaskGroup.appendChild(element);
798
+ let element = this.document.createElementNS("http://www.w3.org/2000/svg", "rect");
799
+ this.backgroundMask = this.createMask("mask-background-color"), this.defs.appendChild(this.backgroundMask),
800
+ element.setAttribute("x", numToAttr(0)), element.setAttribute("y", numToAttr(0)),
801
+ element.setAttribute("width", numToAttr(options.size)), element.setAttribute("height", numToAttr(options.size)),
802
+ element.setAttribute("rx", numToAttr(options.size / 2 * (options.backgroundOptions.round || 0))),
803
+ this.backgroundMask.appendChild(element);
806
804
  }
807
805
  }
808
806
  drawDots(filter) {
809
807
  if (!this.qr) throw new Error("QR code is not defined");
810
808
  let options = this.options, count = this.qr.getModuleCount();
811
- if (count > options.width || count > options.height) throw new Error("The canvas is too small");
812
- let dotSize = this.options.dotsOptions.size, minSize = Math.min(options.width, options.height);
813
- options.imageOptions.mode == ImageMode.background && (minSize -= 2 * dotSize * (options.imageOptions.margin || 0));
814
- let xBeginning = Math.floor((options.width - count * dotSize) / 2), yBeginning = Math.floor((options.height - count * dotSize) / 2), draw = getQrDotFigure(options.dotsOptions.type, options.plugins);
815
- [this.dotsMask, this.dotsMaskGroup] = this.createMask("mask-dot-color"), this.defs.appendChild(this.dotsMask),
816
- options.imageOptions.mode == ImageMode.background && ([this.lightDotsMask, this.lightDotsMaskGroup] = this.createMask("mask-light-dot-color"),
809
+ if (count > options.size) throw new Error("The canvas is too small");
810
+ let dotSize = this.options.dotsOptions.size, size = options.size;
811
+ options.imageOptions.mode == ImageMode.background && (size -= 2 * dotSize * (options.imageOptions.margin || 0));
812
+ let beginning = Math.floor((options.size - count * dotSize) / 2), draw = getQrDotFigure(options.dotsOptions.type, options.plugins);
813
+ this.dotsMask = this.createMask("mask-dot-color"), this.defs.appendChild(this.dotsMask),
814
+ options.imageOptions.mode == ImageMode.background && (this.lightDotsMask = this.createMask("mask-light-dot-color"),
817
815
  this.defs.appendChild(this.lightDotsMask));
818
816
  let margin = 0, additionalDots = 0, fakeCount = count;
819
817
  options.shape === ShapeType.circle ? (margin = this.options.backgroundOptions && this.options.backgroundOptions.margin || 0,
820
- additionalDots = Math.floor((minSize / dotSize - count - 2 * margin) / 2), fakeCount = count + 2 * additionalDots) : options.imageOptions.mode == ImageMode.background && (additionalDots = 1,
818
+ additionalDots = Math.floor((size / dotSize - count - 2 * margin) / 2), fakeCount = count + 2 * additionalDots) : options.imageOptions.mode == ImageMode.background && (additionalDots = 1,
821
819
  fakeCount = count + 2 * additionalDots);
822
- let xFakeBeginning = xBeginning - additionalDots * dotSize, yFakeBeginning = yBeginning - additionalDots * dotSize, colorX = xFakeBeginning, colorY = yFakeBeginning, colorCount = count + 2 * additionalDots;
820
+ let fakeBeginning = beginning - additionalDots * dotSize, colorCount = count + 2 * additionalDots;
823
821
  this._fakeMatrix = new Array(fakeCount);
824
822
  let center = Math.floor(fakeCount / 2);
825
823
  for (let i = 0; i < fakeCount; i++) {
@@ -839,16 +837,16 @@ class QRSVG {
839
837
  for (let j = 0; j < fakeCount; j++) {
840
838
  let jAlign = alignment.find(v => j - additionalDots > v - 3 && j - additionalDots < v + 3);
841
839
  null != this._fakeMatrix[i][j] && (this.lightDotsMask && (draw = iAlign && jAlign && (iAlign != alignment[0] && jAlign != alignment[0] || jAlign != alignment[0] && jAlign != alignment[alignment.length - 1] || iAlign != alignment[0] && iAlign != alignment[alignment.length - 1]) ? getQrDotFigure(DotType.square) : getQrDotFigure(DotType.tinySquare)),
842
- this._fakeMatrix[i][j] ? this.dotsMaskGroup && this.dotsMaskGroup.appendChild(draw({
843
- x: xFakeBeginning + i * dotSize,
844
- y: yFakeBeginning + j * dotSize,
840
+ this._fakeMatrix[i][j] ? this.dotsMask && this.dotsMask.appendChild(draw({
841
+ x: fakeBeginning + i * dotSize,
842
+ y: fakeBeginning + j * dotSize,
845
843
  size: dotSize,
846
844
  document: this.options.document,
847
845
  getNeighbor: (xOffset, yOffset) => !0 === this._fakeMatrix[i + xOffset]?.[j + yOffset],
848
846
  getPRandom: getRng(this._fakeMatrix, i, j)
849
- })) : this.lightDotsMask && this.lightDotsMaskGroup && this.lightDotsMaskGroup.appendChild(draw({
850
- x: xFakeBeginning + i * dotSize,
851
- y: yFakeBeginning + j * dotSize,
847
+ })) : this.lightDotsMask && this.lightDotsMask && this.lightDotsMask.appendChild(draw({
848
+ x: fakeBeginning + i * dotSize,
849
+ y: fakeBeginning + j * dotSize,
852
850
  size: dotSize,
853
851
  document: this.options.document,
854
852
  getNeighbor: (xOffset, yOffset) => !1 === this._fakeMatrix[i + xOffset]?.[j + yOffset],
@@ -860,8 +858,8 @@ class QRSVG {
860
858
  options: options.imageOptions.fill.gradient,
861
859
  color: options.imageOptions.fill.color,
862
860
  additionalRotation: 0,
863
- x: colorX,
864
- y: colorY,
861
+ x: fakeBeginning,
862
+ y: fakeBeginning,
865
863
  height: colorCount * dotSize,
866
864
  width: colorCount * dotSize,
867
865
  name: "light-dot-color"
@@ -869,8 +867,8 @@ class QRSVG {
869
867
  options: options.dotsOptions?.gradient,
870
868
  color: options.dotsOptions.color,
871
869
  additionalRotation: 0,
872
- x: colorX,
873
- y: colorY,
870
+ x: fakeBeginning,
871
+ y: fakeBeginning,
874
872
  height: colorCount * dotSize,
875
873
  width: colorCount * dotSize,
876
874
  name: "dot-color"
@@ -880,11 +878,11 @@ class QRSVG {
880
878
  if (!this.qr) throw new Error("QR code is not defined");
881
879
  let element = this._element, options = this.options;
882
880
  if (!element) throw new Error("Element code is not defined");
883
- let count = this.qr.getModuleCount(), dotSize = this.options.dotsOptions.size, cornersSquareSize = 7 * dotSize, cornersDotSize = 3 * dotSize, xBeginning = Math.floor((options.width - count * dotSize) / 2), yBeginning = Math.floor((options.height - count * dotSize) / 2);
881
+ let count = this.qr.getModuleCount(), dotSize = this.options.dotsOptions.size, cornersSquareSize = 7 * dotSize, cornersDotSize = 3 * dotSize, beginning = Math.floor((options.size - count * dotSize) / 2);
884
882
  [ [ 0, 0, 0 ], [ 1, 0, Math.PI / 2 ], [ 0, 1, -Math.PI / 2 ] ].forEach(([column, row, rotation]) => {
885
- let x = xBeginning + column * dotSize * (count - 7), y = yBeginning + row * dotSize * (count - 7), cornersSquareMask = this.dotsMask, cornersSquareMaskGroup = this.dotsMaskGroup, cornersDotMask = this.dotsMask, cornersDotMaskGroup = this.dotsMaskGroup;
886
- (options.cornersSquareOptions?.gradient || options.cornersSquareOptions?.color) && ([cornersSquareMask, cornersSquareMaskGroup] = this.createMask(`mask-corners-square-color-${column}-${row}`),
887
- this.defs.appendChild(cornersSquareMask), cornersDotMask = cornersSquareMask, cornersDotMaskGroup = cornersSquareMaskGroup,
883
+ let x = beginning + column * dotSize * (count - 7), y = beginning + row * dotSize * (count - 7), cornersSquareMask = this.dotsMask, cornersDotMask = this.dotsMask;
884
+ (options.cornersSquareOptions?.gradient || options.cornersSquareOptions?.color) && (cornersSquareMask = this.createMask(`mask-corners-square-color-${column}-${row}`),
885
+ this.defs.appendChild(cornersSquareMask), cornersDotMask = cornersSquareMask, cornersDotMask = cornersSquareMask,
888
886
  this.createColor({
889
887
  options: options.cornersSquareOptions?.gradient,
890
888
  color: options.cornersSquareOptions?.color,
@@ -910,20 +908,20 @@ class QRSVG {
910
908
  var plugins, type, val;
911
909
  if (pluinCornerSquare) {
912
910
  let [cornerElement, cornerFill] = pluinCornerSquare;
913
- cornersSquareMaskGroup && cornersSquareMaskGroup.appendChild(cornerElement), this.lightDotsMaskGroup && this.lightDotsMaskGroup.appendChild(cornerFill);
911
+ cornersSquareMask && cornersSquareMask.appendChild(cornerElement), this.lightDotsMask && this.lightDotsMask.appendChild(cornerFill);
914
912
  } else if (val = options.cornersSquareOptions?.type, val && cornerSquareTypes.has(val)) {
915
913
  let draw = (type = options.cornersSquareOptions.type, qrCornerSquareFigures[type] || qrCornerSquareFigures[CornerSquareType.square]), [cornerElement, cornerFill] = draw(squareArgs);
916
- cornersSquareMaskGroup && cornersSquareMaskGroup.appendChild(cornerElement), this.lightDotsMaskGroup && this.lightDotsMaskGroup.appendChild(cornerFill);
914
+ cornersSquareMask && cornersSquareMask.appendChild(cornerElement), this.lightDotsMask && this.lightDotsMask.appendChild(cornerFill);
917
915
  } else {
918
916
  let draw = getQrDotFigure(options.cornersSquareOptions?.type || options.dotsOptions.type, options.plugins);
919
- for (let i = 0; i < squareMask.length; i++) for (let j = 0; j < squareMask[i].length; j++) squareMask[i]?.[j] ? cornersSquareMaskGroup && cornersSquareMaskGroup.appendChild(draw({
917
+ for (let i = 0; i < squareMask.length; i++) for (let j = 0; j < squareMask[i].length; j++) squareMask[i]?.[j] ? cornersSquareMask && cornersSquareMask.appendChild(draw({
920
918
  x: x + i * dotSize,
921
919
  y: y + j * dotSize,
922
920
  size: dotSize,
923
921
  document: this.options.document,
924
922
  getNeighbor: (xOffset, yOffset) => !!squareMask[i + xOffset]?.[j + yOffset],
925
923
  getPRandom: getRng(this._fakeMatrix, x / dotSize + i, y / dotSize + j, !1)
926
- })) : this.lightDotsMask && !dotMask[i]?.[j] && this.lightDotsMaskGroup && this.lightDotsMaskGroup.appendChild(draw({
924
+ })) : this.lightDotsMask && !dotMask[i]?.[j] && this.lightDotsMask && this.lightDotsMask.appendChild(draw({
927
925
  x: x + i * dotSize,
928
926
  y: y + j * dotSize,
929
927
  size: dotSize,
@@ -931,7 +929,7 @@ class QRSVG {
931
929
  getNeighbor: (xOffset, yOffset) => !squareMask[i + xOffset]?.[j + yOffset] && !dotMask[i + xOffset]?.[j + yOffset],
932
930
  getPRandom: getRng(this._fakeMatrix, x / dotSize + i, y / dotSize + j, !1)
933
931
  }));
934
- if (this.lightDotsMask) for (let i = -1; i < 8; i++) for (let j = -1; j < 8; j++) -1 != i && 7 != i && -1 != j && 7 != j || this.lightDotsMaskGroup && this.lightDotsMaskGroup.appendChild(draw({
932
+ if (this.lightDotsMask) for (let i = -1; i < 8; i++) for (let j = -1; j < 8; j++) -1 != i && 7 != i && -1 != j && 7 != j || this.lightDotsMask && this.lightDotsMask.appendChild(draw({
935
933
  x: x + i * dotSize,
936
934
  y: y + j * dotSize,
937
935
  size: dotSize,
@@ -943,7 +941,7 @@ class QRSVG {
943
941
  getPRandom: getRng(this._fakeMatrix, x / dotSize + i, y / dotSize + j, !1)
944
942
  }));
945
943
  }
946
- (options.cornersDotOptions?.gradient || options.cornersDotOptions?.color) && ([cornersDotMask, cornersDotMaskGroup] = this.createMask(`mask-corners-dot-color-${column}-${row}`),
944
+ (options.cornersDotOptions?.gradient || options.cornersDotOptions?.color) && (cornersDotMask = this.createMask(`mask-corners-dot-color-${column}-${row}`),
947
945
  this.defs.appendChild(cornersDotMask), this.createColor({
948
946
  options: options.cornersDotOptions?.gradient,
949
947
  color: options.cornersDotOptions?.color,
@@ -968,16 +966,16 @@ class QRSVG {
968
966
  }
969
967
  };
970
968
  }(options.plugins)(dotArgs) : void 0;
971
- if (pluinCornerDot) cornersDotMaskGroup && cornersDotMaskGroup.appendChild(pluinCornerDot); else if (function(val) {
969
+ if (pluinCornerDot) cornersDotMask && cornersDotMask.appendChild(pluinCornerDot); else if (function(val) {
972
970
  return !(!val || !cornerDotTypes.has(val));
973
971
  }(options.cornersDotOptions?.type)) {
974
972
  let draw = function(type) {
975
973
  return qrCornerDotFigures[type] || qrCornerDotFigures[CornerDotType.square];
976
974
  }(options.cornersDotOptions.type);
977
- cornersDotMaskGroup && cornersDotMaskGroup.appendChild(draw(dotArgs));
975
+ cornersDotMask && cornersDotMask.appendChild(draw(dotArgs));
978
976
  } else {
979
977
  let draw = getQrDotFigure(options.cornersDotOptions?.type || options.dotsOptions.type, options.plugins);
980
- for (let i = 0; i < dotMask.length; i++) for (let j = 0; j < dotMask[i].length; j++) dotMask[i]?.[j] && cornersDotMaskGroup && cornersDotMaskGroup.appendChild(draw({
978
+ for (let i = 0; i < dotMask.length; i++) for (let j = 0; j < dotMask[i].length; j++) dotMask[i]?.[j] && cornersDotMask && cornersDotMask.appendChild(draw({
981
979
  x: x + i * dotSize,
982
980
  y: y + j * dotSize,
983
981
  size: dotSize,
@@ -989,9 +987,9 @@ class QRSVG {
989
987
  });
990
988
  }
991
989
  async drawImage({width, height, count, dotSize}) {
992
- let options = this.options, xBeginning = Math.floor((options.width - count * dotSize) / 2), yBeginning = Math.floor((options.height - count * dotSize) / 2), margin = options.imageOptions.margin * dotSize;
990
+ let options = this.options, beginning = Math.floor((options.size - count * dotSize) / 2), margin = options.imageOptions.margin * dotSize;
993
991
  options.imageOptions.mode == ImageMode.background && (margin = 0);
994
- let dx = xBeginning + margin + (count * dotSize - width) / 2, dy = yBeginning + margin + (count * dotSize - height) / 2, dw = width - 2 * margin, dh = height - 2 * margin, imageUrl = await this.imageTools.toDataURL(options.image || ""), image = this.document.createElementNS("http://www.w3.org/2000/svg", "image");
992
+ let dx = beginning + margin + (count * dotSize - width) / 2, dy = beginning + margin + (count * dotSize - height) / 2, dw = width - 2 * margin, dh = height - 2 * margin, imageUrl = await this.imageTools.toDataURL(options.image || ""), image = this.document.createElementNS("http://www.w3.org/2000/svg", "image");
995
993
  if (image.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", imageUrl || ""),
996
994
  imageUrl.startsWith("data:image/svg+xml;")) {
997
995
  let data = imageUrl.substring(19), i = data.indexOf(","), encoding = data.substring(0, i);
@@ -1012,7 +1010,7 @@ class QRSVG {
1012
1010
  let rect = this.document.createElementNS("http://www.w3.org/2000/svg", "rect");
1013
1011
  if (rect.setAttribute("x", numToAttr(x)), rect.setAttribute("y", numToAttr(y)),
1014
1012
  rect.setAttribute("height", numToAttr(height)), rect.setAttribute("width", numToAttr(width)),
1015
- rect.setAttribute("style", `mask:url(#mask-${name})`), options) {
1013
+ rect.setAttribute("clip-path", `url(#mask-${name})`), options) {
1016
1014
  let gradient;
1017
1015
  if (options.type === GradientType.radial) gradient = this.document.createElementNS("http://www.w3.org/2000/svg", "radialGradient"),
1018
1016
  gradient.setAttribute("id", name), gradient.setAttribute("gradientUnits", "userSpaceOnUse"),
@@ -1044,12 +1042,9 @@ class QRSVG {
1044
1042
  this._element.appendChild(rect);
1045
1043
  }
1046
1044
  createMask(id) {
1047
- let options = this.options, mask = this.document.createElementNS("http://www.w3.org/2000/svg", "mask");
1048
- mask.setAttribute("id", id), mask.setAttribute("maskUnits", "userSpaceOnUse"), mask.setAttribute("x", "0"),
1049
- mask.setAttribute("y", "0"), mask.setAttribute("width", numToAttr(options.width)),
1050
- mask.setAttribute("height", numToAttr(options.height));
1051
- let group = this.document.createElementNS("http://www.w3.org/2000/svg", "g");
1052
- return group.setAttribute("fill", "#fff"), mask.appendChild(group), [ mask, group ];
1045
+ let mask = this.document.createElementNS("http://www.w3.org/2000/svg", "clipPath");
1046
+ return mask.setAttribute("id", id), mask.setAttribute("clipPathUnits", "userSpaceOnUse"),
1047
+ mask;
1053
1048
  }
1054
1049
  }
1055
1050
 
@@ -1125,16 +1120,19 @@ let QRCodeStyling$1 = class {
1125
1120
  ...this.options,
1126
1121
  width: size,
1127
1122
  height: size,
1123
+ size,
1128
1124
  errorCorrectionPercent: ErrorCorrectionPercents[this.options.qrOptions.errorCorrectionLevel]
1129
1125
  }), this.svgDrawingPromise = this.qrSVG.drawQR(this.qr).then(() => {
1130
1126
  this.qrSVG?.element && (this.options.plugins?.forEach(plugin => plugin.postProcess?.(this.qrSVG.element, {
1131
1127
  ...this.options,
1132
1128
  width: size,
1133
- height: size
1129
+ height: size,
1130
+ size
1134
1131
  })), this.extension?.(this.qrSVG.element, {
1135
1132
  ...this.options,
1136
1133
  width: size,
1137
- height: size
1134
+ height: size,
1135
+ size
1138
1136
  }));
1139
1137
  });
1140
1138
  }