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