@sec-ant/qr-code-generator
Version:
A QR Code generator in Typescript
2 lines (1 loc) • 11.9 kB
JavaScript
var QrCodeGenerator=function(g){"use strict";var S=Object.defineProperty;var O=(g,f,m)=>f in g?S(g,f,{enumerable:!0,configurable:!0,writable:!0,value:m}):g[f]=m;var h=(g,f,m)=>(O(g,typeof f!="symbol"?f+"":f,m),m);function f(p,t,s){if(t<0||t>31||p>>>t)throw new RangeError("Value out of range");for(let e=t-1;e>=0;e--)s.push(p>>>e&1)}function m(p,t){return(p>>>t&1)!=0}function E(p){if(!p)throw new Error("Assertion error")}const d=class d{constructor(t,s,e){if(this.mode=t,this.numChars=s,this.bitData=e,s<0)throw new RangeError("Invalid argument");this.bitData=e.slice()}static makeBytes(t){const s=[];for(const e of t)f(e,8,s);return new d(R.BYTE,t.length,s)}static makeNumeric(t){if(!d.isNumeric(t))throw new RangeError("String contains non-numeric characters");const s=[];for(let e=0;e<t.length;){const i=Math.min(t.length-e,3);f(parseInt(t.substring(e,e+i),10),i*3+1,s),e+=i}return new d(R.NUMERIC,t.length,s)}static makeAlphanumeric(t){if(!d.isAlphanumeric(t))throw new RangeError("String contains unencodable characters in alphanumeric mode");const s=[];let e;for(e=0;e+2<=t.length;e+=2){let i=d.ALPHANUMERIC_CHARSET.indexOf(t.charAt(e))*45;i+=d.ALPHANUMERIC_CHARSET.indexOf(t.charAt(e+1)),f(i,11,s)}return e<t.length&&f(d.ALPHANUMERIC_CHARSET.indexOf(t.charAt(e)),6,s),new d(R.ALPHANUMERIC,t.length,s)}static makeSegments(t){return t==""?[]:d.isNumeric(t)?[d.makeNumeric(t)]:d.isAlphanumeric(t)?[d.makeAlphanumeric(t)]:[d.makeBytes(d.toUtf8ByteArray(t))]}static makeEci(t){const s=[];if(t<0)throw new RangeError("ECI assignment value out of range");if(t<128)f(t,8,s);else if(t<16384)f(2,2,s),f(t,14,s);else if(t<1e6)f(6,3,s),f(t,21,s);else throw new RangeError("ECI assignment value out of range");return new d(R.ECI,0,s)}static isNumeric(t){return d.NUMERIC_REGEX.test(t)}static isAlphanumeric(t){return d.ALPHANUMERIC_REGEX.test(t)}getData(){return this.bitData.slice()}static getTotalBits(t,s){let e=0;for(const i of t){const o=i.mode.numCharCountBits(s);if(i.numChars>=1<<o)return 1/0;e+=4+o+i.bitData.length}return e}static toUtf8ByteArray(t){t=encodeURI(t);const s=[];for(let e=0;e<t.length;e++)t.charAt(e)!="%"?s.push(t.charCodeAt(e)):(s.push(parseInt(t.substring(e+1,e+3),16)),e+=2);return s}};h(d,"NUMERIC_REGEX",/^[0-9]*$/),h(d,"ALPHANUMERIC_REGEX",/^[A-Z0-9 $%*+./:-]*$/),h(d,"ALPHANUMERIC_CHARSET","0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:");let N=d;const C=class C{constructor(t,s){this.modeBits=t,this.numBitsCharCount=s}numCharCountBits(t){return this.numBitsCharCount[Math.floor((t+7)/17)]}};h(C,"NUMERIC",new C(1,[10,12,14])),h(C,"ALPHANUMERIC",new C(2,[9,11,13])),h(C,"BYTE",new C(4,[8,16,16])),h(C,"KANJI",new C(8,[8,10,12])),h(C,"ECI",new C(7,[0,0,0]));let R=C;const r=class r{constructor(t,s,e,i){h(this,"size");h(this,"mask");h(this,"modules",[]);h(this,"isFunction",[]);if(this.version=t,this.errorCorrectionLevel=s,t<r.MIN_VERSION||t>r.MAX_VERSION)throw new RangeError("Version value out of range");if(i<-1||i>7)throw new RangeError("Mask value out of range");this.size=t*4+17;const o=[];for(let n=0;n<this.size;n++)o.push(!1);for(let n=0;n<this.size;n++)this.modules.push(o.slice()),this.isFunction.push(o.slice());this.drawFunctionPatterns();const a=this.addEccAndInterleave(e);if(this.drawCodewords(a),i==-1){let n=1e9;for(let c=0;c<8;c++){this.applyMask(c),this.drawFormatBits(c);const l=this.getPenaltyScore();l<n&&(i=c,n=l),this.applyMask(c)}}E(0<=i&&i<=7),this.mask=i,this.applyMask(i),this.drawFormatBits(i),this.isFunction=[]}static encodeText(t,s){const e=N.makeSegments(t);return r.encodeSegments(e,s)}static encodeBinary(t,s){const e=N.makeBytes(t);return r.encodeSegments([e],s)}static encodeSegments(t,s,e=1,i=40,o=-1,a=!0){if(!(r.MIN_VERSION<=e&&e<=i&&i<=r.MAX_VERSION)||o<-1||o>7)throw new RangeError("Invalid value");let n,c;for(n=e;;n++){const u=r.getNumDataCodewords(n,s)*8,w=N.getTotalBits(t,n);if(w<=u){c=w;break}if(n>=i)throw new RangeError("Data too long")}for(const u of[P.MEDIUM,P.QUARTILE,P.HIGH])a&&c<=r.getNumDataCodewords(n,u)*8&&(s=u);const l=[];for(const u of t){f(u.mode.modeBits,4,l),f(u.numChars,u.mode.numCharCountBits(n),l);for(const w of u.getData())l.push(w)}E(l.length==c);const b=r.getNumDataCodewords(n,s)*8;E(l.length<=b),f(0,Math.min(4,b-l.length),l),f(0,(8-l.length%8)%8,l),E(l.length%8==0);for(let u=236;l.length<b;u^=253)f(u,8,l);const A=[];for(;A.length*8<l.length;)A.push(0);return l.forEach((u,w)=>A[w>>>3]|=u<<7-(w&7)),new r(n,s,A,o)}getModule(t,s){return 0<=t&&t<this.size&&0<=s&&s<this.size&&this.modules[s][t]}drawFunctionPatterns(){for(let e=0;e<this.size;e++)this.setFunctionModule(6,e,e%2==0),this.setFunctionModule(e,6,e%2==0);this.drawFinderPattern(3,3),this.drawFinderPattern(this.size-4,3),this.drawFinderPattern(3,this.size-4);const t=this.getAlignmentPatternPositions(),s=t.length;for(let e=0;e<s;e++)for(let i=0;i<s;i++)e==0&&i==0||e==0&&i==s-1||e==s-1&&i==0||this.drawAlignmentPattern(t[e],t[i]);this.drawFormatBits(0),this.drawVersion()}drawFormatBits(t){const s=this.errorCorrectionLevel.formatBits<<3|t;let e=s;for(let o=0;o<10;o++)e=e<<1^(e>>>9)*1335;const i=(s<<10|e)^21522;E(i>>>15==0);for(let o=0;o<=5;o++)this.setFunctionModule(8,o,m(i,o));this.setFunctionModule(8,7,m(i,6)),this.setFunctionModule(8,8,m(i,7)),this.setFunctionModule(7,8,m(i,8));for(let o=9;o<15;o++)this.setFunctionModule(14-o,8,m(i,o));for(let o=0;o<8;o++)this.setFunctionModule(this.size-1-o,8,m(i,o));for(let o=8;o<15;o++)this.setFunctionModule(8,this.size-15+o,m(i,o));this.setFunctionModule(8,this.size-8,!0)}drawVersion(){if(this.version<7)return;let t=this.version;for(let e=0;e<12;e++)t=t<<1^(t>>>11)*7973;const s=this.version<<12|t;E(s>>>18==0);for(let e=0;e<18;e++){const i=m(s,e),o=this.size-11+e%3,a=Math.floor(e/3);this.setFunctionModule(o,a,i),this.setFunctionModule(a,o,i)}}drawFinderPattern(t,s){for(let e=-4;e<=4;e++)for(let i=-4;i<=4;i++){const o=Math.max(Math.abs(i),Math.abs(e)),a=t+i,n=s+e;0<=a&&a<this.size&&0<=n&&n<this.size&&this.setFunctionModule(a,n,o!=2&&o!=4)}}drawAlignmentPattern(t,s){for(let e=-2;e<=2;e++)for(let i=-2;i<=2;i++)this.setFunctionModule(t+i,s+e,Math.max(Math.abs(i),Math.abs(e))!=1)}setFunctionModule(t,s,e){this.modules[s][t]=e,this.isFunction[s][t]=!0}addEccAndInterleave(t){const s=this.version,e=this.errorCorrectionLevel;if(t.length!=r.getNumDataCodewords(s,e))throw new RangeError("Invalid argument");const i=r.NUM_ERROR_CORRECTION_BLOCKS[e.ordinal][s],o=r.ECC_CODEWORDS_PER_BLOCK[e.ordinal][s],a=Math.floor(r.getNumRawDataModules(s)/8),n=i-a%i,c=Math.floor(a/i),l=[],b=r.reedSolomonComputeDivisor(o);for(let u=0,w=0;u<i;u++){const I=t.slice(w,w+c-o+(u<n?0:1));w+=I.length;const y=r.reedSolomonComputeRemainder(I,b);u<n&&I.push(0),l.push(I.concat(y))}const A=[];for(let u=0;u<l[0].length;u++)l.forEach((w,I)=>{(u!=c-o||I>=n)&&A.push(w[u])});return E(A.length==a),A}drawCodewords(t){if(t.length!=Math.floor(r.getNumRawDataModules(this.version)/8))throw new RangeError("Invalid argument");let s=0;for(let e=this.size-1;e>=1;e-=2){e==6&&(e=5);for(let i=0;i<this.size;i++)for(let o=0;o<2;o++){const a=e-o,c=(e+1&2)==0?this.size-1-i:i;!this.isFunction[c][a]&&s<t.length*8&&(this.modules[c][a]=m(t[s>>>3],7-(s&7)),s++)}}E(s==t.length*8)}applyMask(t){if(t<0||t>7)throw new RangeError("Mask value out of range");for(let s=0;s<this.size;s++)for(let e=0;e<this.size;e++){let i;switch(t){case 0:i=(e+s)%2==0;break;case 1:i=s%2==0;break;case 2:i=e%3==0;break;case 3:i=(e+s)%3==0;break;case 4:i=(Math.floor(e/3)+Math.floor(s/2))%2==0;break;case 5:i=e*s%2+e*s%3==0;break;case 6:i=(e*s%2+e*s%3)%2==0;break;case 7:i=((e+s)%2+e*s%3)%2==0;break;default:throw new Error("Unreachable")}!this.isFunction[s][e]&&i&&(this.modules[s][e]=!this.modules[s][e])}}getPenaltyScore(){let t=0;for(let o=0;o<this.size;o++){let a=!1,n=0;const c=[0,0,0,0,0,0,0];for(let l=0;l<this.size;l++)this.modules[o][l]==a?(n++,n==5?t+=r.PENALTY_N1:n>5&&t++):(this.finderPenaltyAddHistory(n,c),a||(t+=this.finderPenaltyCountPatterns(c)*r.PENALTY_N3),a=this.modules[o][l],n=1);t+=this.finderPenaltyTerminateAndCount(a,n,c)*r.PENALTY_N3}for(let o=0;o<this.size;o++){let a=!1,n=0;const c=[0,0,0,0,0,0,0];for(let l=0;l<this.size;l++)this.modules[l][o]==a?(n++,n==5?t+=r.PENALTY_N1:n>5&&t++):(this.finderPenaltyAddHistory(n,c),a||(t+=this.finderPenaltyCountPatterns(c)*r.PENALTY_N3),a=this.modules[l][o],n=1);t+=this.finderPenaltyTerminateAndCount(a,n,c)*r.PENALTY_N3}for(let o=0;o<this.size-1;o++)for(let a=0;a<this.size-1;a++){const n=this.modules[o][a];n==this.modules[o][a+1]&&n==this.modules[o+1][a]&&n==this.modules[o+1][a+1]&&(t+=r.PENALTY_N2)}let s=0;for(const o of this.modules)s=o.reduce((a,n)=>a+(n?1:0),s);const e=this.size*this.size,i=Math.ceil(Math.abs(s*20-e*10)/e)-1;return E(0<=i&&i<=9),t+=i*r.PENALTY_N4,E(0<=t&&t<=2568888),t}getAlignmentPatternPositions(){if(this.version==1)return[];{const t=Math.floor(this.version/7)+2,s=this.version==32?26:Math.ceil((this.version*4+4)/(t*2-2))*2,e=[6];for(let i=this.size-7;e.length<t;i-=s)e.splice(1,0,i);return e}}static getNumRawDataModules(t){if(t<r.MIN_VERSION||t>r.MAX_VERSION)throw new RangeError("Version number out of range");let s=(16*t+128)*t+64;if(t>=2){const e=Math.floor(t/7)+2;s-=(25*e-10)*e-55,t>=7&&(s-=36)}return E(208<=s&&s<=29648),s}static getNumDataCodewords(t,s){return Math.floor(r.getNumRawDataModules(t)/8)-r.ECC_CODEWORDS_PER_BLOCK[s.ordinal][t]*r.NUM_ERROR_CORRECTION_BLOCKS[s.ordinal][t]}static reedSolomonComputeDivisor(t){if(t<1||t>255)throw new RangeError("Degree out of range");const s=[];for(let i=0;i<t-1;i++)s.push(0);s.push(1);let e=1;for(let i=0;i<t;i++){for(let o=0;o<s.length;o++)s[o]=r.reedSolomonMultiply(s[o],e),o+1<s.length&&(s[o]^=s[o+1]);e=r.reedSolomonMultiply(e,2)}return s}static reedSolomonComputeRemainder(t,s){const e=s.map(()=>0);for(const i of t){const o=i^e.shift();e.push(0),s.forEach((a,n)=>e[n]^=r.reedSolomonMultiply(a,o))}return e}static reedSolomonMultiply(t,s){if(t>>>8||s>>>8)throw new RangeError("Byte out of range");let e=0;for(let i=7;i>=0;i--)e=e<<1^(e>>>7)*285,e^=(s>>>i&1)*t;return E(e>>>8==0),e}finderPenaltyCountPatterns(t){const s=t[1];E(s<=this.size*3);const e=s>0&&t[2]==s&&t[3]==s*3&&t[4]==s&&t[5]==s;return(e&&t[0]>=s*4&&t[6]>=s?1:0)+(e&&t[6]>=s*4&&t[0]>=s?1:0)}finderPenaltyTerminateAndCount(t,s,e){return t&&(this.finderPenaltyAddHistory(s,e),s=0),s+=this.size,this.finderPenaltyAddHistory(s,e),this.finderPenaltyCountPatterns(e)}finderPenaltyAddHistory(t,s){s[0]==0&&(t+=this.size),s.pop(),s.unshift(t)}};h(r,"MIN_VERSION",1),h(r,"MAX_VERSION",40),h(r,"PENALTY_N1",3),h(r,"PENALTY_N2",3),h(r,"PENALTY_N3",40),h(r,"PENALTY_N4",10),h(r,"ECC_CODEWORDS_PER_BLOCK",[[-1,7,10,15,20,26,18,20,24,30,18,20,24,26,30,22,24,28,30,28,28,28,28,30,30,26,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30],[-1,10,16,26,18,24,16,18,22,22,26,30,22,22,24,24,28,28,26,26,26,26,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28],[-1,13,22,18,26,18,24,18,22,20,24,28,26,24,20,30,24,28,28,26,30,28,30,30,30,30,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30],[-1,17,28,22,16,22,28,26,26,24,28,24,28,22,24,24,30,28,28,26,28,30,24,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30]]),h(r,"NUM_ERROR_CORRECTION_BLOCKS",[[-1,1,1,1,1,1,2,2,2,2,4,4,4,4,4,6,6,6,6,7,8,8,9,9,10,12,12,12,13,14,15,16,17,18,19,19,20,21,22,24,25],[-1,1,1,1,2,2,4,4,4,5,5,5,8,9,9,10,10,11,13,14,16,17,17,18,20,21,23,25,26,28,29,31,33,35,37,38,40,43,45,47,49],[-1,1,1,2,2,4,4,6,6,8,8,8,10,12,16,12,17,16,18,21,20,23,23,25,27,29,34,34,35,38,40,43,45,48,51,53,56,59,62,65,68],[-1,1,1,2,4,4,4,5,6,8,8,11,11,16,16,18,16,19,21,25,25,25,34,30,32,35,37,40,42,45,48,51,54,57,60,63,66,70,74,77,81]]);let B=r;const M=class M{constructor(t,s){this.ordinal=t,this.formatBits=s}};h(M,"LOW",new M(0,1)),h(M,"MEDIUM",new M(1,0)),h(M,"QUARTILE",new M(2,3)),h(M,"HIGH",new M(3,2));let P=M;return g.Ecc=P,g.Mode=R,g.QrCode=B,g.QrSegment=N,Object.defineProperty(g,Symbol.toStringTag,{value:"Module"}),g}({});