@liquid-js/qr-code-styling 5.0.3 → 5.1.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/lib/border-plugin.js +1 -1
- package/lib/border-plugin.js.map +1 -1
- package/lib/core/qr-svg.d.ts +1 -1
- package/lib/plugins/border.d.ts +9 -0
- package/lib/qr-code-styling-node.js +41 -36
- 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 +10 -2
- package/package.json +1 -1
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 /** 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 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 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":["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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"}
|
package/lib/core/qr-svg.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare class QRSVG {
|
|
|
15
15
|
private qr?;
|
|
16
16
|
private document;
|
|
17
17
|
private imageTools;
|
|
18
|
-
constructor(options: Pick<Options, 'width' | 'height' | 'document' | 'imageTools' | 'image' | 'imageOptions' | 'dotsOptions' | 'cornersDotOptions' | 'cornersSquareOptions' | 'backgroundOptions' | 'shape' | 'plugins'> & {
|
|
18
|
+
constructor(options: Pick<Options, 'width' | 'height' | 'size' | 'document' | 'imageTools' | 'image' | 'imageOptions' | 'dotsOptions' | 'cornersDotOptions' | 'cornersSquareOptions' | 'backgroundOptions' | 'shape' | 'plugins'> & {
|
|
19
19
|
errorCorrectionPercent: number;
|
|
20
20
|
});
|
|
21
21
|
get width(): number;
|
package/lib/plugins/border.d.ts
CHANGED
|
@@ -19,6 +19,15 @@ 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;
|
|
@@ -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],
|
|
@@ -693,16 +694,16 @@ class QRSVG {
|
|
|
693
694
|
imageTools;
|
|
694
695
|
constructor(options) {
|
|
695
696
|
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 ${
|
|
697
|
+
let size = numToAttr(options.size);
|
|
698
|
+
this._element.setAttribute("width", size), this._element.setAttribute("height", size),
|
|
699
|
+
this._element.setAttribute("viewBox", `0 0 ${size} ${size}`), this.defs = this.document.createElementNS("http://www.w3.org/2000/svg", "defs"),
|
|
699
700
|
this._element.appendChild(this.defs), this.imageTools = options.imageTools || browserImageTools;
|
|
700
701
|
}
|
|
701
702
|
get width() {
|
|
702
|
-
return this.options.
|
|
703
|
+
return this.options.size;
|
|
703
704
|
}
|
|
704
705
|
get height() {
|
|
705
|
-
return this.options.
|
|
706
|
+
return this.options.size;
|
|
706
707
|
}
|
|
707
708
|
async drawQR(qr) {
|
|
708
709
|
let count = qr.getModuleCount(), typeNumber = parseInt(((count - 17) / 4).toFixed(0), 10), dotSize = this.options.dotsOptions.size, drawImageSize = {
|
|
@@ -714,9 +715,9 @@ class QRSVG {
|
|
|
714
715
|
if (this.qr = qr, this.options.image) {
|
|
715
716
|
let size = await this.imageTools.getSize(this.options.image, this.options.imageOptions.crossOrigin), {imageOptions, errorCorrectionPercent} = this.options;
|
|
716
717
|
if (imageOptions.mode == ImageMode.background) {
|
|
717
|
-
let margin = this.options.backgroundOptions && this.options.backgroundOptions.margin || 0,
|
|
718
|
-
height = height / width *
|
|
719
|
-
height =
|
|
718
|
+
let margin = this.options.backgroundOptions && this.options.backgroundOptions.margin || 0, maxSize = (this.options.size - 2 * margin * dotSize) * imageOptions.imageSize, {width, height} = size;
|
|
719
|
+
height = height / width * maxSize, width = maxSize, height > maxSize && (width = width / height * maxSize,
|
|
720
|
+
height = maxSize), drawImageSize = {
|
|
720
721
|
hideXDots: 0,
|
|
721
722
|
hideYDots: 0,
|
|
722
723
|
width,
|
|
@@ -793,33 +794,34 @@ class QRSVG {
|
|
|
793
794
|
additionalRotation: 0,
|
|
794
795
|
x: 0,
|
|
795
796
|
y: 0,
|
|
796
|
-
height: options.
|
|
797
|
-
width: options.
|
|
797
|
+
height: options.size,
|
|
798
|
+
width: options.size,
|
|
798
799
|
name: "background-color"
|
|
799
800
|
});
|
|
800
|
-
let
|
|
801
|
+
let element = this.document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
801
802
|
[this.backgroundMask, this.backgroundMaskGroup] = this.createMask("mask-background-color"),
|
|
802
|
-
this.defs.appendChild(this.backgroundMask), element.setAttribute("x", numToAttr(
|
|
803
|
-
element.setAttribute("y", numToAttr(
|
|
804
|
-
element.setAttribute("height", numToAttr(size)), element.setAttribute("rx", numToAttr(size / 2 * (options.backgroundOptions.round || 0))),
|
|
803
|
+
this.defs.appendChild(this.backgroundMask), element.setAttribute("x", numToAttr(0)),
|
|
804
|
+
element.setAttribute("y", numToAttr(0)), element.setAttribute("width", numToAttr(options.size)),
|
|
805
|
+
element.setAttribute("height", numToAttr(options.size)), element.setAttribute("rx", numToAttr(options.size / 2 * (options.backgroundOptions.round || 0))),
|
|
805
806
|
this.backgroundMaskGroup.appendChild(element);
|
|
806
807
|
}
|
|
807
808
|
}
|
|
808
809
|
drawDots(filter) {
|
|
809
810
|
if (!this.qr) throw new Error("QR code is not defined");
|
|
810
811
|
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
|
|
812
|
+
if (count > options.size) throw new Error("The canvas is too small");
|
|
813
|
+
let dotSize = this.options.dotsOptions.size;
|
|
814
|
+
options.imageOptions.mode == ImageMode.background && (options.size -= 2 * dotSize * (options.imageOptions.margin || 0));
|
|
815
|
+
let beginning = Math.floor((options.size - count * dotSize) / 2), draw = getQrDotFigure(options.dotsOptions.type, options.plugins);
|
|
815
816
|
[this.dotsMask, this.dotsMaskGroup] = this.createMask("mask-dot-color"), this.defs.appendChild(this.dotsMask),
|
|
816
817
|
options.imageOptions.mode == ImageMode.background && ([this.lightDotsMask, this.lightDotsMaskGroup] = this.createMask("mask-light-dot-color"),
|
|
817
818
|
this.defs.appendChild(this.lightDotsMask));
|
|
818
819
|
let margin = 0, additionalDots = 0, fakeCount = count;
|
|
819
820
|
options.shape === ShapeType.circle ? (margin = this.options.backgroundOptions && this.options.backgroundOptions.margin || 0,
|
|
820
|
-
additionalDots = Math.floor((
|
|
821
|
+
additionalDots = Math.floor((options.size / dotSize - count - 2 * margin) / 2),
|
|
822
|
+
fakeCount = count + 2 * additionalDots) : options.imageOptions.mode == ImageMode.background && (additionalDots = 1,
|
|
821
823
|
fakeCount = count + 2 * additionalDots);
|
|
822
|
-
let
|
|
824
|
+
let fakeBeginning = beginning - additionalDots * dotSize, colorCount = count + 2 * additionalDots;
|
|
823
825
|
this._fakeMatrix = new Array(fakeCount);
|
|
824
826
|
let center = Math.floor(fakeCount / 2);
|
|
825
827
|
for (let i = 0; i < fakeCount; i++) {
|
|
@@ -840,15 +842,15 @@ class QRSVG {
|
|
|
840
842
|
let jAlign = alignment.find(v => j - additionalDots > v - 3 && j - additionalDots < v + 3);
|
|
841
843
|
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
844
|
this._fakeMatrix[i][j] ? this.dotsMaskGroup && this.dotsMaskGroup.appendChild(draw({
|
|
843
|
-
x:
|
|
844
|
-
y:
|
|
845
|
+
x: fakeBeginning + i * dotSize,
|
|
846
|
+
y: fakeBeginning + j * dotSize,
|
|
845
847
|
size: dotSize,
|
|
846
848
|
document: this.options.document,
|
|
847
849
|
getNeighbor: (xOffset, yOffset) => !0 === this._fakeMatrix[i + xOffset]?.[j + yOffset],
|
|
848
850
|
getPRandom: getRng(this._fakeMatrix, i, j)
|
|
849
851
|
})) : this.lightDotsMask && this.lightDotsMaskGroup && this.lightDotsMaskGroup.appendChild(draw({
|
|
850
|
-
x:
|
|
851
|
-
y:
|
|
852
|
+
x: fakeBeginning + i * dotSize,
|
|
853
|
+
y: fakeBeginning + j * dotSize,
|
|
852
854
|
size: dotSize,
|
|
853
855
|
document: this.options.document,
|
|
854
856
|
getNeighbor: (xOffset, yOffset) => !1 === this._fakeMatrix[i + xOffset]?.[j + yOffset],
|
|
@@ -860,8 +862,8 @@ class QRSVG {
|
|
|
860
862
|
options: options.imageOptions.fill.gradient,
|
|
861
863
|
color: options.imageOptions.fill.color,
|
|
862
864
|
additionalRotation: 0,
|
|
863
|
-
x:
|
|
864
|
-
y:
|
|
865
|
+
x: fakeBeginning,
|
|
866
|
+
y: fakeBeginning,
|
|
865
867
|
height: colorCount * dotSize,
|
|
866
868
|
width: colorCount * dotSize,
|
|
867
869
|
name: "light-dot-color"
|
|
@@ -869,8 +871,8 @@ class QRSVG {
|
|
|
869
871
|
options: options.dotsOptions?.gradient,
|
|
870
872
|
color: options.dotsOptions.color,
|
|
871
873
|
additionalRotation: 0,
|
|
872
|
-
x:
|
|
873
|
-
y:
|
|
874
|
+
x: fakeBeginning,
|
|
875
|
+
y: fakeBeginning,
|
|
874
876
|
height: colorCount * dotSize,
|
|
875
877
|
width: colorCount * dotSize,
|
|
876
878
|
name: "dot-color"
|
|
@@ -880,9 +882,9 @@ class QRSVG {
|
|
|
880
882
|
if (!this.qr) throw new Error("QR code is not defined");
|
|
881
883
|
let element = this._element, options = this.options;
|
|
882
884
|
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,
|
|
885
|
+
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
886
|
[ [ 0, 0, 0 ], [ 1, 0, Math.PI / 2 ], [ 0, 1, -Math.PI / 2 ] ].forEach(([column, row, rotation]) => {
|
|
885
|
-
let x =
|
|
887
|
+
let x = beginning + column * dotSize * (count - 7), y = beginning + row * dotSize * (count - 7), cornersSquareMask = this.dotsMask, cornersSquareMaskGroup = this.dotsMaskGroup, cornersDotMask = this.dotsMask, cornersDotMaskGroup = this.dotsMaskGroup;
|
|
886
888
|
(options.cornersSquareOptions?.gradient || options.cornersSquareOptions?.color) && ([cornersSquareMask, cornersSquareMaskGroup] = this.createMask(`mask-corners-square-color-${column}-${row}`),
|
|
887
889
|
this.defs.appendChild(cornersSquareMask), cornersDotMask = cornersSquareMask, cornersDotMaskGroup = cornersSquareMaskGroup,
|
|
888
890
|
this.createColor({
|
|
@@ -989,9 +991,9 @@ class QRSVG {
|
|
|
989
991
|
});
|
|
990
992
|
}
|
|
991
993
|
async drawImage({width, height, count, dotSize}) {
|
|
992
|
-
let options = this.options,
|
|
994
|
+
let options = this.options, beginning = Math.floor((options.size - count * dotSize) / 2), margin = options.imageOptions.margin * dotSize;
|
|
993
995
|
options.imageOptions.mode == ImageMode.background && (margin = 0);
|
|
994
|
-
let dx =
|
|
996
|
+
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
997
|
if (image.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", imageUrl || ""),
|
|
996
998
|
imageUrl.startsWith("data:image/svg+xml;")) {
|
|
997
999
|
let data = imageUrl.substring(19), i = data.indexOf(","), encoding = data.substring(0, i);
|
|
@@ -1046,8 +1048,8 @@ class QRSVG {
|
|
|
1046
1048
|
createMask(id) {
|
|
1047
1049
|
let options = this.options, mask = this.document.createElementNS("http://www.w3.org/2000/svg", "mask");
|
|
1048
1050
|
mask.setAttribute("id", id), mask.setAttribute("maskUnits", "userSpaceOnUse"), mask.setAttribute("x", "0"),
|
|
1049
|
-
mask.setAttribute("y", "0"), mask.setAttribute("width", numToAttr(options.
|
|
1050
|
-
mask.setAttribute("height", numToAttr(options.
|
|
1051
|
+
mask.setAttribute("y", "0"), mask.setAttribute("width", numToAttr(options.size)),
|
|
1052
|
+
mask.setAttribute("height", numToAttr(options.size));
|
|
1051
1053
|
let group = this.document.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
1052
1054
|
return group.setAttribute("fill", "#fff"), mask.appendChild(group), [ mask, group ];
|
|
1053
1055
|
}
|
|
@@ -1125,16 +1127,19 @@ let QRCodeStyling$1 = class {
|
|
|
1125
1127
|
...this.options,
|
|
1126
1128
|
width: size,
|
|
1127
1129
|
height: size,
|
|
1130
|
+
size,
|
|
1128
1131
|
errorCorrectionPercent: ErrorCorrectionPercents[this.options.qrOptions.errorCorrectionLevel]
|
|
1129
1132
|
}), this.svgDrawingPromise = this.qrSVG.drawQR(this.qr).then(() => {
|
|
1130
1133
|
this.qrSVG?.element && (this.options.plugins?.forEach(plugin => plugin.postProcess?.(this.qrSVG.element, {
|
|
1131
1134
|
...this.options,
|
|
1132
1135
|
width: size,
|
|
1133
|
-
height: size
|
|
1136
|
+
height: size,
|
|
1137
|
+
size
|
|
1134
1138
|
})), this.extension?.(this.qrSVG.element, {
|
|
1135
1139
|
...this.options,
|
|
1136
1140
|
width: size,
|
|
1137
|
-
height: size
|
|
1141
|
+
height: size,
|
|
1142
|
+
size
|
|
1138
1143
|
}));
|
|
1139
1144
|
});
|
|
1140
1145
|
}
|