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":[]}