@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 +12 -1
- package/lib/border-plugin.js +1 -1
- package/lib/border-plugin.js.map +1 -1
- package/lib/core/qr-svg.d.ts +1 -4
- package/lib/font-faces-plugin.js +2 -0
- package/lib/font-faces-plugin.js.map +1 -0
- package/lib/plugins/border.d.ts +14 -1
- package/lib/plugins/font-faces.d.ts +19 -0
- package/lib/qr-code-styling-node.js +59 -61
- package/lib/qr-code-styling-node.js.map +1 -1
- package/lib/qr-code-styling.js +1 -1
- package/lib/qr-code-styling.js.map +1 -1
- package/lib/utils/options.d.ts +13 -5
- package/package.json +5 -1
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
|
})
|
package/lib/border-plugin.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
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
|
package/lib/border-plugin.js.map
CHANGED
|
@@ -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":"oBAGKA,eACDC,aACAC,MAAA,oBAEAA,IAAAC,EAAAC,EAAAD,IAAA,CAAA,EAwCUC,EAAAC,IAAA,MAAAD,EAAAE,OAAA,SAAAF,EAAAG,KAAA,OAAAH,EAAAI,MAAA,6BAGWC,cAEAC,SAHrBC,WAAAA,CACqBF,EAEAC,EAAWE,KAAKC,SAASC,QAAQ,IAAIC,UAAU,IAF/CC,KAAAP,cAAAA,EAEAO,KAAAN,SAAAA,CAAiD,CAGtEO,WAAAA,CAAYC,EAAoBC,GAC5B,IAAMC,SAAAA,KACNC,EAAgBL,KAAGP,cAAKa,aAA0BH,EAAGI,WAGjDC,EAAaR,KAAKP,cAAcc,KAAQF,EAC5C,IAAAI,EAAczB,EAAGkB,EAAaM,GAFlBR,KAAIP,cAAKiB,QAAoB,GAAKL,GAG9C,GAAKI,EAAL,CAGAD,EAAYZ,KAAKe,IAAIH,GAErB,IAAAI,GAAQH,EAAIlB,KAAakB,EAAGjB,OAAc,EAC1CqB,GAAQJ,EAAIpB,IAAYoB,EAAGnB,QAAe,IAC5Ba,UAAmB,GAAKH,KAAIP,cAAKqB,OAAmB,MAC3DlB,KAAImB,IAAKN,EAAIjB,MAAciB,EAAGlB,KAAa,EAAIiB,EAAYC,EAAEnB,OAAemB,QAAmBD,KAAiBQ,EAAYR,IAE/HS,EAAQjB,KAAKP,cAAcqB,MAAQI,EAAI,EACvCC,EAAQnB,KAAKP,cAAcqB,MAAQE,EAAWA,EAAWE,KAE/Cd,EAAGgB,6CAAqD,SAC7DC,aAAa,QAASpC,EAA4B,GAAjBkC,EAAQF,KAClDK,EAASD,aAAa,SAAUpC,EAA4B,GAAjBkC,EAAQF,KACnDK,EAASD,aAAa,IAAKpC,EAAU2B,EAAKO,EAAQF,IAClDK,EAASD,aAAa,IAAKpC,EAAU4B,EAAKM,EAAQF,IAClDK,EAASD,aAAa,KAAMpC,EAAUgC,IACtCK,EAASD,aAAa,OAAQ,QAC9BC,EAASD,aAAa,SAAUrB,KAAKP,cAAc8B,SAC1CF,aAAa,eAAgBpC,EAAUuB,IAC5CR,KAAKP,cAAc+B,WACnBF,EAASD,aAAa,mBAAoBrB,KAAKP,cAAc+B,WAGjEtB,EAAIuB,YAAYH,GAEhB,CAACpC,EAAaK,KAAML,EAAaG,IAAKH,EAAaM,MAAON,EAAaI,QAAQoC,QAAQC,IACnF,MAAa3B,mBAAQ4B,OACTC,IAAUF,MAClBG,EAAQ,CACR,IAAIC,EAAOC,MAAMC,KAAK/B,EAAIgC,YAAYC,KAAK/C,GAAiD,QAA3CA,EAAkBgD,QAAQC,eACtEN,IACDA,EAAO3B,EAASgB,gBAAgB,6BAA8B,QAC9DlB,EAAIuB,YAAYM,QAEpBO,EAAalC,EAAGgB,6CAAqD,QACrEb,GAAUuB,QAAeD,EAAItB,MAAY,cACjCP,KAAKP,cAAcqB,MAAQI,EAAIX,EAAO,EAAI,IAC1CP,KAAKP,cAAcqB,MAAQE,EAAWA,GAAYE,EAAIX,EAAO,GAC7DoB,GACJ,KAAKzC,EAAaG,IACdiD,EAAQjB,aACJ,IACAkB,CAAA,KAAY3B,KAAMC,EAAKI,EAAQE,QAC5BA,OACDF,KAASA,YAAgBA,MAAUA,QACnC,EAAKE,OACLF,KAASA,WAAeA,MAAUA,OAClC,EAAIE,OACJF,KAASA,WAAeA,KAASA,OACjC,EAAIE,OACJF,KAASA,YAAgBA,KAASA,QACjCE,KAEP,WACCjC,EAAaI,OACVU,KAAKP,cAAcqB,MACnBG,GAAgB,EAAPV,EAAW,EAEpBY,GAAgB,EAAPZ,EAAW,EACxB+B,EAAQjB,aACJ,IACAkB,CAAA,KAAY3B,KAAMC,EAAKI,EAAQE,QAC5BA,OACDF,KAASA,YAAgBA,KAASA,OAClC,EAAIE,OACJF,KAASA,WAAeA,KAASA,OACjC,EAAIE,OACJF,KAASA,WAAeA,MAAUA,QAClC,EAAKE,OACLF,KAASA,YAAgBA,MAAUA,QAClCE,KAEP,WACCjC,EAAaK,KACd+C,EAAQjB,aACJ,IACAkB,CAAA,KAAY3B,EAAKK,EAAQE,KAASN,OAChCM,OACAF,KAASA,YAAgBA,KAASA,QAClC,EAAKE,OACLF,KAASA,YAAgBA,MAAUA,QACnC,EAAKE,OACLF,KAASA,WAAeA,MAAUA,OAClC,EAAIE,OACJF,KAASA,WAAeA,KAASA,OACjCE,KAEN,MACJ,KAAKjC,EAAaM,MACd8C,EAAQjB,aACJ,IACAkB,CAAA,KAAY3B,EAAKK,EAAQE,KAASN,QAC/BM,OACDF,KAASA,WAAeA,MAAUA,OAClC,EAAIE,OACJF,KAASA,WAAeA,KAASA,OACjC,EAAIE,OACJF,KAASA,YAAgBA,KAASA,QAClC,EAAKE,OACLF,KAASA,YAAgBA,MAAUA,QAClCE,KAIfqB,EAAQ,eAAGb,UAA0BjC,aAC7B2B,aAAa,KAAMmB,GAC3BF,EAAQjB,aAAa,OAAQ,QAE7B,IAAAoB,EAAUrC,EAAGgB,6CAAqD,SAClEqB,EAAKpB,aAAa,cAAeS,EAAOY,MAAQb,EAAQa,MAAQ,cAChED,EAAKpB,aAAa,OAAQS,EAAOP,OAASM,EAAQN,OAAS,UACtDF,aAAa,cAAepC,EAAU6C,EAAOa,YAAcd,EAAQc,YAAc,WACtFF,EAAKpB,aAAa,aAAcS,EAAOc,WAAaf,EAAQe,WAAa,YACpEvB,aAAa,YAAapC,EAAUsB,IACzCkC,EAAKI,YAAcf,EAAOgB,SAE1BC,EAAc3C,EAAGgB,6CAAqD,aAC7D4B,eAAe,+BAAgC,aAAc,IAAMR,GAC5EO,EAAS1B,aAAa,cAAe,OACrC0B,EAAS1B,aAAa,cAAe,UACrC0B,EAAStB,YAAYgB,IAErBb,EAAUxB,EAAGgB,6CAAqD,SAC7DK,YAAYsB,KAEZtB,YAAYa,GACjBpC,EAAIuB,YAAYG,EAlGR,IAuGZ5B,KAAKP,cAAcwD,aACflB,EAAOC,MAAMC,KAAK/B,EAAIgC,YAAYC,KAAK/C,GAAiD,QAA3CA,EAAkBgD,QAAQC,kBAEvEN,EAAO3B,EAASgB,gBAAgB,6BAA8B,QAC9DlB,EAAIuB,YAAYM,KAEpBmB,EAAW9C,EAAGgB,6CAAqD,UAE7DyB,YAAc7C,KAAKP,cAAcwD,UACvClB,EAAKN,YAAYyB,GA/IrB,CAP4C"}
|
package/lib/core/qr-svg.d.ts
CHANGED
|
@@ -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"}
|
package/lib/plugins/border.d.ts
CHANGED
|
@@ -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
|
-
/**
|
|
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
|
|
697
|
-
this._element.setAttribute("width",
|
|
698
|
-
this._element.setAttribute("viewBox", `0 0 ${
|
|
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.
|
|
700
|
+
return this.options.size;
|
|
703
701
|
}
|
|
704
702
|
get height() {
|
|
705
|
-
return this.options.
|
|
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,
|
|
718
|
-
height = height / width *
|
|
719
|
-
height =
|
|
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.
|
|
797
|
-
width: options.
|
|
794
|
+
height: options.size,
|
|
795
|
+
width: options.size,
|
|
798
796
|
name: "background-color"
|
|
799
797
|
});
|
|
800
|
-
let
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
element.setAttribute("
|
|
804
|
-
element.setAttribute("
|
|
805
|
-
this.
|
|
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.
|
|
812
|
-
let dotSize = this.options.dotsOptions.size,
|
|
813
|
-
options.imageOptions.mode == ImageMode.background && (
|
|
814
|
-
let
|
|
815
|
-
|
|
816
|
-
options.imageOptions.mode == ImageMode.background && (
|
|
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((
|
|
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
|
|
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.
|
|
843
|
-
x:
|
|
844
|
-
y:
|
|
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.
|
|
850
|
-
x:
|
|
851
|
-
y:
|
|
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:
|
|
864
|
-
y:
|
|
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:
|
|
873
|
-
y:
|
|
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,
|
|
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 =
|
|
886
|
-
(options.cornersSquareOptions?.gradient || options.cornersSquareOptions?.color) && (
|
|
887
|
-
this.defs.appendChild(cornersSquareMask), cornersDotMask = cornersSquareMask,
|
|
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
|
-
|
|
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
|
-
|
|
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] ?
|
|
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.
|
|
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.
|
|
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) && (
|
|
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)
|
|
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
|
-
|
|
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] &&
|
|
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,
|
|
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 =
|
|
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("
|
|
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
|
|
1048
|
-
mask.setAttribute("id", id), mask.setAttribute("
|
|
1049
|
-
mask
|
|
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
|
}
|