5ae20e82ccb2cbfec079225d3083b3f8b6a4dbf15c8970da66b429e172afaee5.json raw
1 {"ast":null,"code":"const Utils = require('./utils');\nconst ECLevel = require('./error-correction-level');\nconst BitBuffer = require('./bit-buffer');\nconst BitMatrix = require('./bit-matrix');\nconst AlignmentPattern = require('./alignment-pattern');\nconst FinderPattern = require('./finder-pattern');\nconst MaskPattern = require('./mask-pattern');\nconst ECCode = require('./error-correction-code');\nconst ReedSolomonEncoder = require('./reed-solomon-encoder');\nconst Version = require('./version');\nconst FormatInfo = require('./format-info');\nconst Mode = require('./mode');\nconst Segments = require('./segments');\n\n/**\n * QRCode for JavaScript\n *\n * modified by Ryan Day for nodejs support\n * Copyright (c) 2011 Ryan Day\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/mit-license.php\n *\n//---------------------------------------------------------------------\n// QRCode for JavaScript\n//\n// Copyright (c) 2009 Kazuhiko Arase\n//\n// URL: http://www.d-project.com/\n//\n// Licensed under the MIT license:\n// http://www.opensource.org/licenses/mit-license.php\n//\n// The word \"QR Code\" is registered trademark of\n// DENSO WAVE INCORPORATED\n// http://www.denso-wave.com/qrcode/faqpatent-e.html\n//\n//---------------------------------------------------------------------\n*/\n\n/**\n * Add finder patterns bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Number} version QR Code version\n */\nfunction setupFinderPattern(matrix, version) {\n const size = matrix.size;\n const pos = FinderPattern.getPositions(version);\n for (let i = 0; i < pos.length; i++) {\n const row = pos[i][0];\n const col = pos[i][1];\n for (let r = -1; r <= 7; r++) {\n if (row + r <= -1 || size <= row + r) continue;\n for (let c = -1; c <= 7; c++) {\n if (col + c <= -1 || size <= col + c) continue;\n if (r >= 0 && r <= 6 && (c === 0 || c === 6) || c >= 0 && c <= 6 && (r === 0 || r === 6) || r >= 2 && r <= 4 && c >= 2 && c <= 4) {\n matrix.set(row + r, col + c, true, true);\n } else {\n matrix.set(row + r, col + c, false, true);\n }\n }\n }\n }\n}\n\n/**\n * Add timing pattern bits to matrix\n *\n * Note: this function must be called before {@link setupAlignmentPattern}\n *\n * @param {BitMatrix} matrix Modules matrix\n */\nfunction setupTimingPattern(matrix) {\n const size = matrix.size;\n for (let r = 8; r < size - 8; r++) {\n const value = r % 2 === 0;\n matrix.set(r, 6, value, true);\n matrix.set(6, r, value, true);\n }\n}\n\n/**\n * Add alignment patterns bits to matrix\n *\n * Note: this function must be called after {@link setupTimingPattern}\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Number} version QR Code version\n */\nfunction setupAlignmentPattern(matrix, version) {\n const pos = AlignmentPattern.getPositions(version);\n for (let i = 0; i < pos.length; i++) {\n const row = pos[i][0];\n const col = pos[i][1];\n for (let r = -2; r <= 2; r++) {\n for (let c = -2; c <= 2; c++) {\n if (r === -2 || r === 2 || c === -2 || c === 2 || r === 0 && c === 0) {\n matrix.set(row + r, col + c, true, true);\n } else {\n matrix.set(row + r, col + c, false, true);\n }\n }\n }\n }\n}\n\n/**\n * Add version info bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Number} version QR Code version\n */\nfunction setupVersionInfo(matrix, version) {\n const size = matrix.size;\n const bits = Version.getEncodedBits(version);\n let row, col, mod;\n for (let i = 0; i < 18; i++) {\n row = Math.floor(i / 3);\n col = i % 3 + size - 8 - 3;\n mod = (bits >> i & 1) === 1;\n matrix.set(row, col, mod, true);\n matrix.set(col, row, mod, true);\n }\n}\n\n/**\n * Add format info bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level\n * @param {Number} maskPattern Mask pattern reference value\n */\nfunction setupFormatInfo(matrix, errorCorrectionLevel, maskPattern) {\n const size = matrix.size;\n const bits = FormatInfo.getEncodedBits(errorCorrectionLevel, maskPattern);\n let i, mod;\n for (i = 0; i < 15; i++) {\n mod = (bits >> i & 1) === 1;\n\n // vertical\n if (i < 6) {\n matrix.set(i, 8, mod, true);\n } else if (i < 8) {\n matrix.set(i + 1, 8, mod, true);\n } else {\n matrix.set(size - 15 + i, 8, mod, true);\n }\n\n // horizontal\n if (i < 8) {\n matrix.set(8, size - i - 1, mod, true);\n } else if (i < 9) {\n matrix.set(8, 15 - i - 1 + 1, mod, true);\n } else {\n matrix.set(8, 15 - i - 1, mod, true);\n }\n }\n\n // fixed module\n matrix.set(size - 8, 8, 1, true);\n}\n\n/**\n * Add encoded data bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Uint8Array} data Data codewords\n */\nfunction setupData(matrix, data) {\n const size = matrix.size;\n let inc = -1;\n let row = size - 1;\n let bitIndex = 7;\n let byteIndex = 0;\n for (let col = size - 1; col > 0; col -= 2) {\n if (col === 6) col--;\n while (true) {\n for (let c = 0; c < 2; c++) {\n if (!matrix.isReserved(row, col - c)) {\n let dark = false;\n if (byteIndex < data.length) {\n dark = (data[byteIndex] >>> bitIndex & 1) === 1;\n }\n matrix.set(row, col - c, dark);\n bitIndex--;\n if (bitIndex === -1) {\n byteIndex++;\n bitIndex = 7;\n }\n }\n }\n row += inc;\n if (row < 0 || size <= row) {\n row -= inc;\n inc = -inc;\n break;\n }\n }\n }\n}\n\n/**\n * Create encoded codewords from data input\n *\n * @param {Number} version QR Code version\n * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level\n * @param {ByteData} data Data input\n * @return {Uint8Array} Buffer containing encoded codewords\n */\nfunction createData(version, errorCorrectionLevel, segments) {\n // Prepare data buffer\n const buffer = new BitBuffer();\n segments.forEach(function (data) {\n // prefix data with mode indicator (4 bits)\n buffer.put(data.mode.bit, 4);\n\n // Prefix data with character count indicator.\n // The character count indicator is a string of bits that represents the\n // number of characters that are being encoded.\n // The character count indicator must be placed after the mode indicator\n // and must be a certain number of bits long, depending on the QR version\n // and data mode\n // @see {@link Mode.getCharCountIndicator}.\n buffer.put(data.getLength(), Mode.getCharCountIndicator(data.mode, version));\n\n // add binary data sequence to buffer\n data.write(buffer);\n });\n\n // Calculate required number of bits\n const totalCodewords = Utils.getSymbolTotalCodewords(version);\n const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel);\n const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8;\n\n // Add a terminator.\n // If the bit string is shorter than the total number of required bits,\n // a terminator of up to four 0s must be added to the right side of the string.\n // If the bit string is more than four bits shorter than the required number of bits,\n // add four 0s to the end.\n if (buffer.getLengthInBits() + 4 <= dataTotalCodewordsBits) {\n buffer.put(0, 4);\n }\n\n // If the bit string is fewer than four bits shorter, add only the number of 0s that\n // are needed to reach the required number of bits.\n\n // After adding the terminator, if the number of bits in the string is not a multiple of 8,\n // pad the string on the right with 0s to make the string's length a multiple of 8.\n while (buffer.getLengthInBits() % 8 !== 0) {\n buffer.putBit(0);\n }\n\n // Add pad bytes if the string is still shorter than the total number of required bits.\n // Extend the buffer to fill the data capacity of the symbol corresponding to\n // the Version and Error Correction Level by adding the Pad Codewords 11101100 (0xEC)\n // and 00010001 (0x11) alternately.\n const remainingByte = (dataTotalCodewordsBits - buffer.getLengthInBits()) / 8;\n for (let i = 0; i < remainingByte; i++) {\n buffer.put(i % 2 ? 0x11 : 0xEC, 8);\n }\n return createCodewords(buffer, version, errorCorrectionLevel);\n}\n\n/**\n * Encode input data with Reed-Solomon and return codewords with\n * relative error correction bits\n *\n * @param {BitBuffer} bitBuffer Data to encode\n * @param {Number} version QR Code version\n * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level\n * @return {Uint8Array} Buffer containing encoded codewords\n */\nfunction createCodewords(bitBuffer, version, errorCorrectionLevel) {\n // Total codewords for this QR code version (Data + Error correction)\n const totalCodewords = Utils.getSymbolTotalCodewords(version);\n\n // Total number of error correction codewords\n const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel);\n\n // Total number of data codewords\n const dataTotalCodewords = totalCodewords - ecTotalCodewords;\n\n // Total number of blocks\n const ecTotalBlocks = ECCode.getBlocksCount(version, errorCorrectionLevel);\n\n // Calculate how many blocks each group should contain\n const blocksInGroup2 = totalCodewords % ecTotalBlocks;\n const blocksInGroup1 = ecTotalBlocks - blocksInGroup2;\n const totalCodewordsInGroup1 = Math.floor(totalCodewords / ecTotalBlocks);\n const dataCodewordsInGroup1 = Math.floor(dataTotalCodewords / ecTotalBlocks);\n const dataCodewordsInGroup2 = dataCodewordsInGroup1 + 1;\n\n // Number of EC codewords is the same for both groups\n const ecCount = totalCodewordsInGroup1 - dataCodewordsInGroup1;\n\n // Initialize a Reed-Solomon encoder with a generator polynomial of degree ecCount\n const rs = new ReedSolomonEncoder(ecCount);\n let offset = 0;\n const dcData = new Array(ecTotalBlocks);\n const ecData = new Array(ecTotalBlocks);\n let maxDataSize = 0;\n const buffer = new Uint8Array(bitBuffer.buffer);\n\n // Divide the buffer into the required number of blocks\n for (let b = 0; b < ecTotalBlocks; b++) {\n const dataSize = b < blocksInGroup1 ? dataCodewordsInGroup1 : dataCodewordsInGroup2;\n\n // extract a block of data from buffer\n dcData[b] = buffer.slice(offset, offset + dataSize);\n\n // Calculate EC codewords for this data block\n ecData[b] = rs.encode(dcData[b]);\n offset += dataSize;\n maxDataSize = Math.max(maxDataSize, dataSize);\n }\n\n // Create final data\n // Interleave the data and error correction codewords from each block\n const data = new Uint8Array(totalCodewords);\n let index = 0;\n let i, r;\n\n // Add data codewords\n for (i = 0; i < maxDataSize; i++) {\n for (r = 0; r < ecTotalBlocks; r++) {\n if (i < dcData[r].length) {\n data[index++] = dcData[r][i];\n }\n }\n }\n\n // Apped EC codewords\n for (i = 0; i < ecCount; i++) {\n for (r = 0; r < ecTotalBlocks; r++) {\n data[index++] = ecData[r][i];\n }\n }\n return data;\n}\n\n/**\n * Build QR Code symbol\n *\n * @param {String} data Input string\n * @param {Number} version QR Code version\n * @param {ErrorCorretionLevel} errorCorrectionLevel Error level\n * @param {MaskPattern} maskPattern Mask pattern\n * @return {Object} Object containing symbol data\n */\nfunction createSymbol(data, version, errorCorrectionLevel, maskPattern) {\n let segments;\n if (Array.isArray(data)) {\n segments = Segments.fromArray(data);\n } else if (typeof data === 'string') {\n let estimatedVersion = version;\n if (!estimatedVersion) {\n const rawSegments = Segments.rawSplit(data);\n\n // Estimate best version that can contain raw splitted segments\n estimatedVersion = Version.getBestVersionForData(rawSegments, errorCorrectionLevel);\n }\n\n // Build optimized segments\n // If estimated version is undefined, try with the highest version\n segments = Segments.fromString(data, estimatedVersion || 40);\n } else {\n throw new Error('Invalid data');\n }\n\n // Get the min version that can contain data\n const bestVersion = Version.getBestVersionForData(segments, errorCorrectionLevel);\n\n // If no version is found, data cannot be stored\n if (!bestVersion) {\n throw new Error('The amount of data is too big to be stored in a QR Code');\n }\n\n // If not specified, use min version as default\n if (!version) {\n version = bestVersion;\n\n // Check if the specified version can contain the data\n } else if (version < bestVersion) {\n throw new Error('\\n' + 'The chosen QR Code version cannot contain this amount of data.\\n' + 'Minimum version required to store current data is: ' + bestVersion + '.\\n');\n }\n const dataBits = createData(version, errorCorrectionLevel, segments);\n\n // Allocate matrix buffer\n const moduleCount = Utils.getSymbolSize(version);\n const modules = new BitMatrix(moduleCount);\n\n // Add function modules\n setupFinderPattern(modules, version);\n setupTimingPattern(modules);\n setupAlignmentPattern(modules, version);\n\n // Add temporary dummy bits for format info just to set them as reserved.\n // This is needed to prevent these bits from being masked by {@link MaskPattern.applyMask}\n // since the masking operation must be performed only on the encoding region.\n // These blocks will be replaced with correct values later in code.\n setupFormatInfo(modules, errorCorrectionLevel, 0);\n if (version >= 7) {\n setupVersionInfo(modules, version);\n }\n\n // Add data codewords\n setupData(modules, dataBits);\n if (isNaN(maskPattern)) {\n // Find best mask pattern\n maskPattern = MaskPattern.getBestMask(modules, setupFormatInfo.bind(null, modules, errorCorrectionLevel));\n }\n\n // Apply mask pattern\n MaskPattern.applyMask(maskPattern, modules);\n\n // Replace format info bits with correct values\n setupFormatInfo(modules, errorCorrectionLevel, maskPattern);\n return {\n modules: modules,\n version: version,\n errorCorrectionLevel: errorCorrectionLevel,\n maskPattern: maskPattern,\n segments: segments\n };\n}\n\n/**\n * QR Code\n *\n * @param {String | Array} data Input data\n * @param {Object} options Optional configurations\n * @param {Number} options.version QR Code version\n * @param {String} options.errorCorrectionLevel Error correction level\n * @param {Function} options.toSJISFunc Helper func to convert utf8 to sjis\n */\nexports.create = function create(data, options) {\n if (typeof data === 'undefined' || data === '') {\n throw new Error('No input text');\n }\n let errorCorrectionLevel = ECLevel.M;\n let version;\n let mask;\n if (typeof options !== 'undefined') {\n // Use higher error correction level as default\n errorCorrectionLevel = ECLevel.from(options.errorCorrectionLevel, ECLevel.M);\n version = Version.from(options.version);\n mask = MaskPattern.from(options.maskPattern);\n if (options.toSJISFunc) {\n Utils.setToSJISFunction(options.toSJISFunc);\n }\n }\n return createSymbol(data, version, errorCorrectionLevel, mask);\n};","map":null,"metadata":{},"sourceType":"script","externalDependencies":[]}