Website Structure

This commit is contained in:
supalerk-ar66 2026-01-13 10:46:40 +07:00
parent 62812f2090
commit 71f0676a62
22365 changed files with 4265753 additions and 791 deletions

22
Frontend-Learner/node_modules/uqr/LICENSE generated vendored Normal file
View file

@ -0,0 +1,22 @@
MIT License
Copyright (c) Project Nayuki
Copyright (c) 2023 Anthony Fu <https://github.com/antfu>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

138
Frontend-Learner/node_modules/uqr/README.md generated vendored Normal file
View file

@ -0,0 +1,138 @@
# uqr
[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![bundle][bundle-src]][bundle-href]
[![License][license-src]][license-href]
[![JSDocs][jsdocs-src]][jsdocs-href]
<!-- [![Codecov][codecov-src]][codecov-href] -->
Generate QR Code universally, in any runtime, to ANSI, Unicode or SVG. ES module , zero dependency, tree-shakable.
## Install
```bash
# Using npm
npm install uqr
# Using yarn
yarn add uqr
# Using pnpm
pnpm add uqr
```
## Usage
```ts
import {
encode,
renderANSI,
renderSVG,
renderUnicode,
renderUnicodeCompact,
} from 'uqr'
const svg = renderSVG('Hello, World!')
const ansi = renderANSI('https://192.168.1.100:3000', {
// Error correction level
ecc: 'L',
// Border width
border: 2,
})
// display QR Code in terminal
console.log(ansi)
```
## API
### `encode`
Encode plain text or binary data into QR Code represented by a 2D array.
```ts
import { encode } from 'uqr'
const {
data, // 2D array of boolean, representing the QR Code
version, // QR Code version
size, // size of the QR Code
} = encode(text, options)
```
### `renderANSI`
Render QR Code to [ANSI colored](https://ss64.com/nt/syntax-ansi.html) string.
```ts
import { renderANSI } from 'uqr'
const string = renderANSI(text, options)
console.log(string)
```
### `renderUnicode`
Render QR Code to Unicode string for each pixel. By default it uses `█` and `░` to represent black and white pixels, and it can be customizable.
```ts
import { renderUnicode } from 'uqr'
const string = renderUnicode(text, {
blackChar: '█',
whiteChar: '░',
// ...other options
})
```
### `renderUnicodeCompact`
Render QR Code with two rows into one line with unicode `▀`, `▄`, `█`, ` `. It is useful when you want to display QR Code in terminal with limited height.
```ts
import { renderUnicodeCompact } from 'uqr'
const string = renderUnicodeCompact(text, options)
console.log(string)
```
### `renderSVG`
Render QR Code to SVG string.
```ts
import { renderSVG } from 'uqr'
const string = renderSVG(text, options)
```
## Credits
QR Code generation algorithm is modified from [nayuki/QR-Code-generator](https://github.com/nayuki/QR-Code-generator/blob/master/typescript-javascript/qrcodegen.ts) by Project Nayuki.
CLI renders are inspired by [qrcode-terminal](https://github.com/gtanner/qrcode-terminal).
## License
[MIT](./LICENSE) License
<!-- Badges -->
[npm-version-src]: https://img.shields.io/npm/v/uqr?style=flat&colorA=18181B&colorB=F0DB4F
[npm-version-href]: https://npmjs.com/package/uqr
[npm-downloads-src]: https://img.shields.io/npm/dm/uqr?style=flat&colorA=18181B&colorB=F0DB4F
[npm-downloads-href]: https://npmjs.com/package/uqr
[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/uqr/main?style=flat&colorA=18181B&colorB=F0DB4F
[codecov-href]: https://codecov.io/gh/unjs/uqr
[bundle-src]: https://img.shields.io/bundlephobia/minzip/uqr?style=flat&colorA=18181B&colorB=F0DB4F
[bundle-href]: https://bundlephobia.com/result?p=uqr
[license-src]: https://img.shields.io/github/license/unjs/uqr.svg?style=flat&colorA=18181B&colorB=F0DB4F
[license-href]: https://github.com/unjs/uqr/blob/main/LICENSE
[jsdocs-src]: https://img.shields.io/badge/jsDocs.io-reference-18181B?style=flat&colorA=18181B&colorB=F0DB4F
[jsdocs-href]: https://www.jsdocs.io/package/uqr

747
Frontend-Learner/node_modules/uqr/dist/index.cjs generated vendored Normal file
View file

@ -0,0 +1,747 @@
'use strict';
var QrCodeDataType = /* @__PURE__ */ ((QrCodeDataType2) => {
QrCodeDataType2[QrCodeDataType2["Border"] = -1] = "Border";
QrCodeDataType2[QrCodeDataType2["Data"] = 0] = "Data";
QrCodeDataType2[QrCodeDataType2["Function"] = 1] = "Function";
QrCodeDataType2[QrCodeDataType2["Position"] = 2] = "Position";
QrCodeDataType2[QrCodeDataType2["Timing"] = 3] = "Timing";
QrCodeDataType2[QrCodeDataType2["Alignment"] = 4] = "Alignment";
return QrCodeDataType2;
})(QrCodeDataType || {});
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
const LOW = [0, 1];
const MEDIUM = [1, 0];
const QUARTILE = [2, 3];
const HIGH = [3, 2];
const EccMap = {
L: LOW,
M: MEDIUM,
Q: QUARTILE,
H: HIGH
};
const NUMERIC_REGEX = /^[0-9]*$/;
const ALPHANUMERIC_REGEX = /^[A-Z0-9 $%*+.\/:-]*$/;
const ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
const MIN_VERSION = 1;
const MAX_VERSION = 40;
const PENALTY_N1 = 3;
const PENALTY_N2 = 3;
const PENALTY_N3 = 40;
const PENALTY_N4 = 10;
const ECC_CODEWORDS_PER_BLOCK = [
// Version: (note that index 0 is for padding, and is set to an illegal value)
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
[-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],
// Low
[-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],
// Medium
[-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],
// Quartile
[-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]
// High
];
const NUM_ERROR_CORRECTION_BLOCKS = [
// Version: (note that index 0 is for padding, and is set to an illegal value)
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
[-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],
// Low
[-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],
// Medium
[-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],
// Quartile
[-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]
// High
];
class QrCode {
/* -- Constructor (low level) and fields -- */
// Creates a new QR Code with the given version number,
// error correction level, data codeword bytes, and mask number.
// This is a low-level API that most users should not use directly.
// A mid-level API is the encodeSegments() function.
constructor(version, ecc, dataCodewords, msk) {
this.version = version;
this.ecc = ecc;
/* -- Fields -- */
// The width and height of this QR Code, measured in modules, between
// 21 and 177 (inclusive). This is equal to version * 4 + 17.
__publicField(this, "size");
// The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive).
// Even if a QR Code is created with automatic masking requested (mask = -1),
// the resulting object still has a mask value between 0 and 7.
__publicField(this, "mask");
// The modules of this QR Code (false = light, true = dark).
// Immutable after constructor finishes. Accessed through getModule().
__publicField(this, "modules", []);
__publicField(this, "types", []);
if (version < MIN_VERSION || version > MAX_VERSION)
throw new RangeError("Version value out of range");
if (msk < -1 || msk > 7)
throw new RangeError("Mask value out of range");
this.size = version * 4 + 17;
const row = Array.from({ length: this.size }, () => false);
for (let i = 0; i < this.size; i++) {
this.modules.push(row.slice());
this.types.push(row.map(() => 0));
}
this.drawFunctionPatterns();
const allCodewords = this.addEccAndInterleave(dataCodewords);
this.drawCodewords(allCodewords);
if (msk === -1) {
let minPenalty = 1e9;
for (let i = 0; i < 8; i++) {
this.applyMask(i);
this.drawFormatBits(i);
const penalty = this.getPenaltyScore();
if (penalty < minPenalty) {
msk = i;
minPenalty = penalty;
}
this.applyMask(i);
}
}
this.mask = msk;
this.applyMask(msk);
this.drawFormatBits(msk);
}
/* -- Accessor methods -- */
// Returns the color of the module (pixel) at the given coordinates, which is false
// for light or true for dark. The top left corner has the coordinates (x=0, y=0).
// If the given coordinates are out of bounds, then false (light) is returned.
getModule(x, y) {
return x >= 0 && x < this.size && y >= 0 && y < this.size && this.modules[y][x];
}
/* -- Private helper methods for constructor: Drawing function modules -- */
// Reads this object's version field, and draws and marks all function modules.
drawFunctionPatterns() {
for (let i = 0; i < this.size; i++) {
this.setFunctionModule(6, i, i % 2 === 0, QrCodeDataType.Timing);
this.setFunctionModule(i, 6, i % 2 === 0, QrCodeDataType.Timing);
}
this.drawFinderPattern(3, 3);
this.drawFinderPattern(this.size - 4, 3);
this.drawFinderPattern(3, this.size - 4);
const alignPatPos = this.getAlignmentPatternPositions();
const numAlign = alignPatPos.length;
for (let i = 0; i < numAlign; i++) {
for (let j = 0; j < numAlign; j++) {
if (!(i === 0 && j === 0 || i === 0 && j === numAlign - 1 || i === numAlign - 1 && j === 0))
this.drawAlignmentPattern(alignPatPos[i], alignPatPos[j]);
}
}
this.drawFormatBits(0);
this.drawVersion();
}
// Draws two copies of the format bits (with its own error correction code)
// based on the given mask and this object's error correction level field.
drawFormatBits(mask) {
const data = this.ecc[1] << 3 | mask;
let rem = data;
for (let i = 0; i < 10; i++)
rem = rem << 1 ^ (rem >>> 9) * 1335;
const bits = (data << 10 | rem) ^ 21522;
for (let i = 0; i <= 5; i++)
this.setFunctionModule(8, i, getBit(bits, i));
this.setFunctionModule(8, 7, getBit(bits, 6));
this.setFunctionModule(8, 8, getBit(bits, 7));
this.setFunctionModule(7, 8, getBit(bits, 8));
for (let i = 9; i < 15; i++)
this.setFunctionModule(14 - i, 8, getBit(bits, i));
for (let i = 0; i < 8; i++)
this.setFunctionModule(this.size - 1 - i, 8, getBit(bits, i));
for (let i = 8; i < 15; i++)
this.setFunctionModule(8, this.size - 15 + i, getBit(bits, i));
this.setFunctionModule(8, this.size - 8, true);
}
// Draws two copies of the version bits (with its own error correction code),
// based on this object's version field, iff 7 <= version <= 40.
drawVersion() {
if (this.version < 7)
return;
let rem = this.version;
for (let i = 0; i < 12; i++)
rem = rem << 1 ^ (rem >>> 11) * 7973;
const bits = this.version << 12 | rem;
for (let i = 0; i < 18; i++) {
const color = getBit(bits, i);
const a = this.size - 11 + i % 3;
const b = Math.floor(i / 3);
this.setFunctionModule(a, b, color);
this.setFunctionModule(b, a, color);
}
}
// Draws a 9*9 finder pattern including the border separator,
// with the center module at (x, y). Modules can be out of bounds.
drawFinderPattern(x, y) {
for (let dy = -4; dy <= 4; dy++) {
for (let dx = -4; dx <= 4; dx++) {
const dist = Math.max(Math.abs(dx), Math.abs(dy));
const xx = x + dx;
const yy = y + dy;
if (xx >= 0 && xx < this.size && yy >= 0 && yy < this.size)
this.setFunctionModule(xx, yy, dist !== 2 && dist !== 4, QrCodeDataType.Position);
}
}
}
// Draws a 5*5 alignment pattern, with the center module
// at (x, y). All modules must be in bounds.
drawAlignmentPattern(x, y) {
for (let dy = -2; dy <= 2; dy++) {
for (let dx = -2; dx <= 2; dx++) {
this.setFunctionModule(
x + dx,
y + dy,
Math.max(Math.abs(dx), Math.abs(dy)) !== 1,
QrCodeDataType.Alignment
);
}
}
}
// Sets the color of a module and marks it as a function module.
// Only used by the constructor. Coordinates must be in bounds.
setFunctionModule(x, y, isDark, type = QrCodeDataType.Function) {
this.modules[y][x] = isDark;
this.types[y][x] = type;
}
/* -- Private helper methods for constructor: Codewords and masking -- */
// Returns a new byte string representing the given data with the appropriate error correction
// codewords appended to it, based on this object's version and error correction level.
addEccAndInterleave(data) {
const ver = this.version;
const ecl = this.ecc;
if (data.length !== getNumDataCodewords(ver, ecl))
throw new RangeError("Invalid argument");
const numBlocks = NUM_ERROR_CORRECTION_BLOCKS[ecl[0]][ver];
const blockEccLen = ECC_CODEWORDS_PER_BLOCK[ecl[0]][ver];
const rawCodewords = Math.floor(getNumRawDataModules(ver) / 8);
const numShortBlocks = numBlocks - rawCodewords % numBlocks;
const shortBlockLen = Math.floor(rawCodewords / numBlocks);
const blocks = [];
const rsDiv = reedSolomonComputeDivisor(blockEccLen);
for (let i = 0, k = 0; i < numBlocks; i++) {
const dat = data.slice(k, k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1));
k += dat.length;
const ecc = reedSolomonComputeRemainder(dat, rsDiv);
if (i < numShortBlocks)
dat.push(0);
blocks.push(dat.concat(ecc));
}
const result = [];
for (let i = 0; i < blocks[0].length; i++) {
blocks.forEach((block, j) => {
if (i !== shortBlockLen - blockEccLen || j >= numShortBlocks)
result.push(block[i]);
});
}
return result;
}
// Draws the given sequence of 8-bit codewords (data and error correction) onto the entire
// data area of this QR Code. Function modules need to be marked off before this is called.
drawCodewords(data) {
if (data.length !== Math.floor(getNumRawDataModules(this.version) / 8))
throw new RangeError("Invalid argument");
let i = 0;
for (let right = this.size - 1; right >= 1; right -= 2) {
if (right === 6)
right = 5;
for (let vert = 0; vert < this.size; vert++) {
for (let j = 0; j < 2; j++) {
const x = right - j;
const upward = (right + 1 & 2) === 0;
const y = upward ? this.size - 1 - vert : vert;
if (!this.types[y][x] && i < data.length * 8) {
this.modules[y][x] = getBit(data[i >>> 3], 7 - (i & 7));
i++;
}
}
}
}
}
// XORs the codeword modules in this QR Code with the given mask pattern.
// The function modules must be marked and the codeword bits must be drawn
// before masking. Due to the arithmetic of XOR, calling applyMask() with
// the same mask value a second time will undo the mask. A final well-formed
// QR Code needs exactly one (not zero, two, etc.) mask applied.
applyMask(mask) {
if (mask < 0 || mask > 7)
throw new RangeError("Mask value out of range");
for (let y = 0; y < this.size; y++) {
for (let x = 0; x < this.size; x++) {
let invert;
switch (mask) {
case 0:
invert = (x + y) % 2 === 0;
break;
case 1:
invert = y % 2 === 0;
break;
case 2:
invert = x % 3 === 0;
break;
case 3:
invert = (x + y) % 3 === 0;
break;
case 4:
invert = (Math.floor(x / 3) + Math.floor(y / 2)) % 2 === 0;
break;
case 5:
invert = x * y % 2 + x * y % 3 === 0;
break;
case 6:
invert = (x * y % 2 + x * y % 3) % 2 === 0;
break;
case 7:
invert = ((x + y) % 2 + x * y % 3) % 2 === 0;
break;
default:
throw new Error("Unreachable");
}
if (!this.types[y][x] && invert)
this.modules[y][x] = !this.modules[y][x];
}
}
}
// Calculates and returns the penalty score based on state of this QR Code's current modules.
// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.
getPenaltyScore() {
let result = 0;
for (let y = 0; y < this.size; y++) {
let runColor = false;
let runX = 0;
const runHistory = [0, 0, 0, 0, 0, 0, 0];
for (let x = 0; x < this.size; x++) {
if (this.modules[y][x] === runColor) {
runX++;
if (runX === 5)
result += PENALTY_N1;
else if (runX > 5)
result++;
} else {
this.finderPenaltyAddHistory(runX, runHistory);
if (!runColor)
result += this.finderPenaltyCountPatterns(runHistory) * PENALTY_N3;
runColor = this.modules[y][x];
runX = 1;
}
}
result += this.finderPenaltyTerminateAndCount(runColor, runX, runHistory) * PENALTY_N3;
}
for (let x = 0; x < this.size; x++) {
let runColor = false;
let runY = 0;
const runHistory = [0, 0, 0, 0, 0, 0, 0];
for (let y = 0; y < this.size; y++) {
if (this.modules[y][x] === runColor) {
runY++;
if (runY === 5)
result += PENALTY_N1;
else if (runY > 5)
result++;
} else {
this.finderPenaltyAddHistory(runY, runHistory);
if (!runColor)
result += this.finderPenaltyCountPatterns(runHistory) * PENALTY_N3;
runColor = this.modules[y][x];
runY = 1;
}
}
result += this.finderPenaltyTerminateAndCount(runColor, runY, runHistory) * PENALTY_N3;
}
for (let y = 0; y < this.size - 1; y++) {
for (let x = 0; x < this.size - 1; x++) {
const color = this.modules[y][x];
if (color === this.modules[y][x + 1] && color === this.modules[y + 1][x] && color === this.modules[y + 1][x + 1])
result += PENALTY_N2;
}
}
let dark = 0;
for (const row of this.modules)
dark = row.reduce((sum, color) => sum + (color ? 1 : 0), dark);
const total = this.size * this.size;
const k = Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1;
result += k * PENALTY_N4;
return result;
}
/* -- Private helper functions -- */
// Returns an ascending list of positions of alignment patterns for this version number.
// Each position is in the range [0,177), and are used on both the x and y axes.
// This could be implemented as lookup table of 40 variable-length lists of integers.
getAlignmentPatternPositions() {
if (this.version === 1) {
return [];
} else {
const numAlign = Math.floor(this.version / 7) + 2;
const step = this.version === 32 ? 26 : Math.ceil((this.version * 4 + 4) / (numAlign * 2 - 2)) * 2;
const result = [6];
for (let pos = this.size - 7; result.length < numAlign; pos -= step)
result.splice(1, 0, pos);
return result;
}
}
// Can only be called immediately after a light run is added, and
// returns either 0, 1, or 2. A helper function for getPenaltyScore().
finderPenaltyCountPatterns(runHistory) {
const n = runHistory[1];
const core = n > 0 && runHistory[2] === n && runHistory[3] === n * 3 && runHistory[4] === n && runHistory[5] === n;
return (core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0) + (core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0);
}
// Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore().
finderPenaltyTerminateAndCount(currentRunColor, currentRunLength, runHistory) {
if (currentRunColor) {
this.finderPenaltyAddHistory(currentRunLength, runHistory);
currentRunLength = 0;
}
currentRunLength += this.size;
this.finderPenaltyAddHistory(currentRunLength, runHistory);
return this.finderPenaltyCountPatterns(runHistory);
}
// Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore().
finderPenaltyAddHistory(currentRunLength, runHistory) {
if (runHistory[0] === 0)
currentRunLength += this.size;
runHistory.pop();
runHistory.unshift(currentRunLength);
}
}
function appendBits(val, len, bb) {
if (len < 0 || len > 31 || val >>> len !== 0)
throw new RangeError("Value out of range");
for (let i = len - 1; i >= 0; i--)
bb.push(val >>> i & 1);
}
function getBit(x, i) {
return (x >>> i & 1) !== 0;
}
class QrSegment {
// Creates a new QR Code segment with the given attributes and data.
// The character count (numChars) must agree with the mode and the bit buffer length,
// but the constraint isn't checked. The given bit buffer is cloned and stored.
constructor(mode, numChars, bitData) {
this.mode = mode;
this.numChars = numChars;
this.bitData = bitData;
if (numChars < 0)
throw new RangeError("Invalid argument");
this.bitData = bitData.slice();
}
/* -- Methods -- */
// Returns a new copy of the data bits of this segment.
getData() {
return this.bitData.slice();
}
}
const MODE_NUMERIC = [1, 10, 12, 14];
const MODE_ALPHANUMERIC = [2, 9, 11, 13];
const MODE_BYTE = [4, 8, 16, 16];
function numCharCountBits(mode, ver) {
return mode[Math.floor((ver + 7) / 17) + 1];
}
function makeBytes(data) {
const bb = [];
for (const b of data)
appendBits(b, 8, bb);
return new QrSegment(MODE_BYTE, data.length, bb);
}
function makeNumeric(digits) {
if (!isNumeric(digits))
throw new RangeError("String contains non-numeric characters");
const bb = [];
for (let i = 0; i < digits.length; ) {
const n = Math.min(digits.length - i, 3);
appendBits(Number.parseInt(digits.substring(i, i + n), 10), n * 3 + 1, bb);
i += n;
}
return new QrSegment(MODE_NUMERIC, digits.length, bb);
}
function makeAlphanumeric(text) {
if (!isAlphanumeric(text))
throw new RangeError("String contains unencodable characters in alphanumeric mode");
const bb = [];
let i;
for (i = 0; i + 2 <= text.length; i += 2) {
let temp = ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45;
temp += ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1));
appendBits(temp, 11, bb);
}
if (i < text.length)
appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6, bb);
return new QrSegment(MODE_ALPHANUMERIC, text.length, bb);
}
function makeSegments(text) {
if (text === "")
return [];
else if (isNumeric(text))
return [makeNumeric(text)];
else if (isAlphanumeric(text))
return [makeAlphanumeric(text)];
else
return [makeBytes(toUtf8ByteArray(text))];
}
function isNumeric(text) {
return NUMERIC_REGEX.test(text);
}
function isAlphanumeric(text) {
return ALPHANUMERIC_REGEX.test(text);
}
function getTotalBits(segs, version) {
let result = 0;
for (const seg of segs) {
const ccbits = numCharCountBits(seg.mode, version);
if (seg.numChars >= 1 << ccbits)
return Number.POSITIVE_INFINITY;
result += 4 + ccbits + seg.bitData.length;
}
return result;
}
function toUtf8ByteArray(str) {
str = encodeURI(str);
const result = [];
for (let i = 0; i < str.length; i++) {
if (str.charAt(i) !== "%") {
result.push(str.charCodeAt(i));
} else {
result.push(Number.parseInt(str.substring(i + 1, i + 3), 16));
i += 2;
}
}
return result;
}
function getNumRawDataModules(ver) {
if (ver < MIN_VERSION || ver > MAX_VERSION)
throw new RangeError("Version number out of range");
let result = (16 * ver + 128) * ver + 64;
if (ver >= 2) {
const numAlign = Math.floor(ver / 7) + 2;
result -= (25 * numAlign - 10) * numAlign - 55;
if (ver >= 7)
result -= 36;
}
return result;
}
function getNumDataCodewords(ver, ecl) {
return Math.floor(getNumRawDataModules(ver) / 8) - ECC_CODEWORDS_PER_BLOCK[ecl[0]][ver] * NUM_ERROR_CORRECTION_BLOCKS[ecl[0]][ver];
}
function reedSolomonComputeDivisor(degree) {
if (degree < 1 || degree > 255)
throw new RangeError("Degree out of range");
const result = [];
for (let i = 0; i < degree - 1; i++)
result.push(0);
result.push(1);
let root = 1;
for (let i = 0; i < degree; i++) {
for (let j = 0; j < result.length; j++) {
result[j] = reedSolomonMultiply(result[j], root);
if (j + 1 < result.length)
result[j] ^= result[j + 1];
}
root = reedSolomonMultiply(root, 2);
}
return result;
}
function reedSolomonComputeRemainder(data, divisor) {
const result = divisor.map((_) => 0);
for (const b of data) {
const factor = b ^ result.shift();
result.push(0);
divisor.forEach((coef, i) => result[i] ^= reedSolomonMultiply(coef, factor));
}
return result;
}
function reedSolomonMultiply(x, y) {
if (x >>> 8 !== 0 || y >>> 8 !== 0)
throw new RangeError("Byte out of range");
let z = 0;
for (let i = 7; i >= 0; i--) {
z = z << 1 ^ (z >>> 7) * 285;
z ^= (y >>> i & 1) * x;
}
return z;
}
function encodeSegments(segs, ecl, minVersion = 1, maxVersion = 40, mask = -1, boostEcl = true) {
if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7)
throw new RangeError("Invalid value");
let version;
let dataUsedBits;
for (version = minVersion; ; version++) {
const dataCapacityBits2 = getNumDataCodewords(version, ecl) * 8;
const usedBits = getTotalBits(segs, version);
if (usedBits <= dataCapacityBits2) {
dataUsedBits = usedBits;
break;
}
if (version >= maxVersion)
throw new RangeError("Data too long");
}
for (const newEcl of [MEDIUM, QUARTILE, HIGH]) {
if (boostEcl && dataUsedBits <= getNumDataCodewords(version, newEcl) * 8)
ecl = newEcl;
}
const bb = [];
for (const seg of segs) {
appendBits(seg.mode[0], 4, bb);
appendBits(seg.numChars, numCharCountBits(seg.mode, version), bb);
for (const b of seg.getData())
bb.push(b);
}
const dataCapacityBits = getNumDataCodewords(version, ecl) * 8;
appendBits(0, Math.min(4, dataCapacityBits - bb.length), bb);
appendBits(0, (8 - bb.length % 8) % 8, bb);
for (let padByte = 236; bb.length < dataCapacityBits; padByte ^= 236 ^ 17)
appendBits(padByte, 8, bb);
const dataCodewords = Array.from({ length: Math.ceil(bb.length / 8) }, () => 0);
bb.forEach((b, i) => dataCodewords[i >>> 3] |= b << 7 - (i & 7));
return new QrCode(version, ecl, dataCodewords, mask);
}
function encode(data, options) {
const {
ecc = "L",
boostEcc = false,
minVersion = 1,
maxVersion = 40,
maskPattern = -1,
border = 1
} = options || {};
const segment = typeof data === "string" ? makeSegments(data) : Array.isArray(data) ? [makeBytes(data)] : void 0;
if (!segment)
throw new Error(`uqr only supports encoding string and binary data, but got: ${typeof data}`);
const qr = encodeSegments(
segment,
EccMap[ecc],
minVersion,
maxVersion,
maskPattern,
boostEcc
);
const result = addBorder({
version: qr.version,
maskPattern: qr.mask,
size: qr.size,
data: qr.modules,
types: qr.types
}, border);
if (options?.invert)
result.data = result.data.map((row) => row.map((mod) => !mod));
options?.onEncoded?.(result);
return result;
}
function addBorder(input, border = 1) {
if (!border)
return input;
const { size } = input;
const newSize = size + border * 2;
input.size = newSize;
input.data.forEach((row) => {
for (let i = 0; i < border; i++) {
row.unshift(false);
row.push(false);
}
});
for (let i = 0; i < border; i++) {
input.data.unshift(Array.from({ length: newSize }, (_) => false));
input.data.push(Array.from({ length: newSize }, (_) => false));
}
const b = QrCodeDataType.Border;
input.types.forEach((row) => {
for (let i = 0; i < border; i++) {
row.unshift(b);
row.push(b);
}
});
for (let i = 0; i < border; i++) {
input.types.unshift(Array.from({ length: newSize }, (_) => b));
input.types.push(Array.from({ length: newSize }, (_) => b));
}
return input;
}
function getDataAt(data, x, y, defaults = false) {
if (x < 0 || y < 0 || x >= data.length || y >= data.length)
return defaults;
return data[y][x];
}
function renderUnicode(data, options = {}) {
const {
whiteChar = "\u2588",
blackChar = "\u2591"
} = options;
const result = encode(data, options);
return result.data.map((row) => {
return row.map((mod) => mod ? blackChar : whiteChar).join("");
}).join("\n");
}
function renderANSI(data, options = {}) {
return renderUnicode(data, {
...options,
blackChar: "\x1B[40m\u3000\x1B[0m",
whiteChar: "\x1B[47m\u3000\x1B[0m"
});
}
function renderUnicodeCompact(data, options = {}) {
const platte = {
WHITE_ALL: "\u2588",
WHITE_BLACK: "\u2580",
BLACK_WHITE: "\u2584",
BLACK_ALL: " "
};
const result = encode(data, options);
const WHITE = false;
const BLACK = true;
const at = (x, y) => getDataAt(result.data, x, y, true);
const lines = [];
let line = "";
for (let row = 0; row < result.size; row += 2) {
for (let col = 0; col < result.size; col++) {
if (at(col, row) === WHITE && at(col, row + 1) === WHITE)
line += platte.WHITE_ALL;
else if (at(col, row) === WHITE && at(col, row + 1) === BLACK)
line += platte.WHITE_BLACK;
else if (at(col, row) === BLACK && at(col, row + 1) === WHITE)
line += platte.BLACK_WHITE;
else
line += platte.BLACK_ALL;
}
lines.push(line);
line = "";
}
return lines.join("\n");
}
function renderSVG(data, options = {}) {
const result = encode(data, options);
const {
pixelSize = 10,
whiteColor = "white",
blackColor = "black"
} = options;
const height = result.size * pixelSize;
const width = result.size * pixelSize;
let svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}">`;
const pathes = [];
for (let row = 0; row < result.size; row++) {
for (let col = 0; col < result.size; col++) {
const x = col * pixelSize;
const y = row * pixelSize;
if (result.data[row][col])
pathes.push(`M${x},${y}h${pixelSize}v${pixelSize}h-${pixelSize}z`);
}
}
svg += `<rect fill="${whiteColor}" width="${width}" height="${height}"/>`;
svg += `<path fill="${blackColor}" d="${pathes.join("")}"/>`;
svg += "</svg>";
return svg;
}
exports.QrCodeDataType = QrCodeDataType;
exports.encode = encode;
exports.renderANSI = renderANSI;
exports.renderSVG = renderSVG;
exports.renderUnicode = renderUnicode;
exports.renderUnicodeCompact = renderUnicodeCompact;

132
Frontend-Learner/node_modules/uqr/dist/index.d.cts generated vendored Normal file
View file

@ -0,0 +1,132 @@
/**
* String or binary
*/
type QrCodeGenerateData = string | Readonly<Array<number>>;
interface QrCodeGenerateOptions {
/**
* Error correction level
*
* L - Allows recovery of up to 7% data loss
* M - Allows recovery of up to 15% data loss
* Q - Allows recovery of up to 25% data loss
* H - Allows recovery of up to 30% data loss
*
* @default 'L'
*/
ecc?: 'L' | 'M' | 'Q' | 'H';
/**
* Mask pattern to use
*
* @default -1 (auto)
*/
maskPattern?: number;
/**
* Boost the error correction level to the maximum allowed by the version and size
*/
boostEcc?: boolean;
/**
* Minimum version of the QR code (1-40)
* @default 1
*/
minVersion?: number;
/**
* Maximum version of the QR code (1-40)
* @default 40
*/
maxVersion?: number;
/**
* Border around the QR code
*
* @default 1
*/
border?: number;
/**
* Invert black and white
*/
invert?: boolean;
/**
* Callback function to receive the generated QR Code
*/
onEncoded?: (qr: QrCodeGenerateResult) => void;
}
declare enum QrCodeDataType {
Border = -1,
Data = 0,
Function = 1,
Position = 2,
Timing = 3,
Alignment = 4
}
interface QrCodeGenerateResult {
/**
* QR Code version
*/
version: number;
/**
* Width and height of the QR Code array
*/
size: number;
/**
* Mask pattern used
*/
maskPattern: number;
/**
* Two dimensional array representing the QR Code
*
* `true` for black, `false` for white
*/
data: boolean[][];
/**
* Data type of each module
*/
types: QrCodeDataType[][];
}
interface QrCodeGenerateInvertableOptions extends QrCodeGenerateOptions {
invert?: boolean;
}
interface QrCodeGenerateUnicodeOptions extends QrCodeGenerateInvertableOptions {
whiteChar?: string;
blackChar?: string;
}
interface QrCodeGenerateSvgOptions extends QrCodeGenerateOptions {
/**
* Size of each pixel
*
* @default 20
*/
pixelSize?: number;
/**
* Color of the white module
*
* @default 'white'
*/
whiteColor?: string;
/**
* Color of the black module
*
* @default 'black'
*/
blackColor?: string;
}
declare function encode(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): QrCodeGenerateResult;
/**
* Render QR Code with unicode ``, ``
*/
declare function renderUnicode(data: QrCodeGenerateData, options?: QrCodeGenerateUnicodeOptions): string;
/**
* Render QR Code with ANSI color for terminal
*/
declare function renderANSI(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): string;
/**
* Render QR Code with two rows into one line with unicode ``, ``, ``, ` `
*/
declare function renderUnicodeCompact(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): string;
/**
* Render QR Code with ANSI color for terminal
*/
declare function renderSVG(data: QrCodeGenerateData, options?: QrCodeGenerateSvgOptions): string;
export { QrCodeDataType, QrCodeGenerateData, QrCodeGenerateInvertableOptions, QrCodeGenerateOptions, QrCodeGenerateResult, QrCodeGenerateSvgOptions, QrCodeGenerateUnicodeOptions, encode, renderANSI, renderSVG, renderUnicode, renderUnicodeCompact };

132
Frontend-Learner/node_modules/uqr/dist/index.d.mts generated vendored Normal file
View file

@ -0,0 +1,132 @@
/**
* String or binary
*/
type QrCodeGenerateData = string | Readonly<Array<number>>;
interface QrCodeGenerateOptions {
/**
* Error correction level
*
* L - Allows recovery of up to 7% data loss
* M - Allows recovery of up to 15% data loss
* Q - Allows recovery of up to 25% data loss
* H - Allows recovery of up to 30% data loss
*
* @default 'L'
*/
ecc?: 'L' | 'M' | 'Q' | 'H';
/**
* Mask pattern to use
*
* @default -1 (auto)
*/
maskPattern?: number;
/**
* Boost the error correction level to the maximum allowed by the version and size
*/
boostEcc?: boolean;
/**
* Minimum version of the QR code (1-40)
* @default 1
*/
minVersion?: number;
/**
* Maximum version of the QR code (1-40)
* @default 40
*/
maxVersion?: number;
/**
* Border around the QR code
*
* @default 1
*/
border?: number;
/**
* Invert black and white
*/
invert?: boolean;
/**
* Callback function to receive the generated QR Code
*/
onEncoded?: (qr: QrCodeGenerateResult) => void;
}
declare enum QrCodeDataType {
Border = -1,
Data = 0,
Function = 1,
Position = 2,
Timing = 3,
Alignment = 4
}
interface QrCodeGenerateResult {
/**
* QR Code version
*/
version: number;
/**
* Width and height of the QR Code array
*/
size: number;
/**
* Mask pattern used
*/
maskPattern: number;
/**
* Two dimensional array representing the QR Code
*
* `true` for black, `false` for white
*/
data: boolean[][];
/**
* Data type of each module
*/
types: QrCodeDataType[][];
}
interface QrCodeGenerateInvertableOptions extends QrCodeGenerateOptions {
invert?: boolean;
}
interface QrCodeGenerateUnicodeOptions extends QrCodeGenerateInvertableOptions {
whiteChar?: string;
blackChar?: string;
}
interface QrCodeGenerateSvgOptions extends QrCodeGenerateOptions {
/**
* Size of each pixel
*
* @default 20
*/
pixelSize?: number;
/**
* Color of the white module
*
* @default 'white'
*/
whiteColor?: string;
/**
* Color of the black module
*
* @default 'black'
*/
blackColor?: string;
}
declare function encode(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): QrCodeGenerateResult;
/**
* Render QR Code with unicode ``, ``
*/
declare function renderUnicode(data: QrCodeGenerateData, options?: QrCodeGenerateUnicodeOptions): string;
/**
* Render QR Code with ANSI color for terminal
*/
declare function renderANSI(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): string;
/**
* Render QR Code with two rows into one line with unicode ``, ``, ``, ` `
*/
declare function renderUnicodeCompact(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): string;
/**
* Render QR Code with ANSI color for terminal
*/
declare function renderSVG(data: QrCodeGenerateData, options?: QrCodeGenerateSvgOptions): string;
export { QrCodeDataType, QrCodeGenerateData, QrCodeGenerateInvertableOptions, QrCodeGenerateOptions, QrCodeGenerateResult, QrCodeGenerateSvgOptions, QrCodeGenerateUnicodeOptions, encode, renderANSI, renderSVG, renderUnicode, renderUnicodeCompact };

132
Frontend-Learner/node_modules/uqr/dist/index.d.ts generated vendored Normal file
View file

@ -0,0 +1,132 @@
/**
* String or binary
*/
type QrCodeGenerateData = string | Readonly<Array<number>>;
interface QrCodeGenerateOptions {
/**
* Error correction level
*
* L - Allows recovery of up to 7% data loss
* M - Allows recovery of up to 15% data loss
* Q - Allows recovery of up to 25% data loss
* H - Allows recovery of up to 30% data loss
*
* @default 'L'
*/
ecc?: 'L' | 'M' | 'Q' | 'H';
/**
* Mask pattern to use
*
* @default -1 (auto)
*/
maskPattern?: number;
/**
* Boost the error correction level to the maximum allowed by the version and size
*/
boostEcc?: boolean;
/**
* Minimum version of the QR code (1-40)
* @default 1
*/
minVersion?: number;
/**
* Maximum version of the QR code (1-40)
* @default 40
*/
maxVersion?: number;
/**
* Border around the QR code
*
* @default 1
*/
border?: number;
/**
* Invert black and white
*/
invert?: boolean;
/**
* Callback function to receive the generated QR Code
*/
onEncoded?: (qr: QrCodeGenerateResult) => void;
}
declare enum QrCodeDataType {
Border = -1,
Data = 0,
Function = 1,
Position = 2,
Timing = 3,
Alignment = 4
}
interface QrCodeGenerateResult {
/**
* QR Code version
*/
version: number;
/**
* Width and height of the QR Code array
*/
size: number;
/**
* Mask pattern used
*/
maskPattern: number;
/**
* Two dimensional array representing the QR Code
*
* `true` for black, `false` for white
*/
data: boolean[][];
/**
* Data type of each module
*/
types: QrCodeDataType[][];
}
interface QrCodeGenerateInvertableOptions extends QrCodeGenerateOptions {
invert?: boolean;
}
interface QrCodeGenerateUnicodeOptions extends QrCodeGenerateInvertableOptions {
whiteChar?: string;
blackChar?: string;
}
interface QrCodeGenerateSvgOptions extends QrCodeGenerateOptions {
/**
* Size of each pixel
*
* @default 20
*/
pixelSize?: number;
/**
* Color of the white module
*
* @default 'white'
*/
whiteColor?: string;
/**
* Color of the black module
*
* @default 'black'
*/
blackColor?: string;
}
declare function encode(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): QrCodeGenerateResult;
/**
* Render QR Code with unicode ``, ``
*/
declare function renderUnicode(data: QrCodeGenerateData, options?: QrCodeGenerateUnicodeOptions): string;
/**
* Render QR Code with ANSI color for terminal
*/
declare function renderANSI(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): string;
/**
* Render QR Code with two rows into one line with unicode ``, ``, ``, ` `
*/
declare function renderUnicodeCompact(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): string;
/**
* Render QR Code with ANSI color for terminal
*/
declare function renderSVG(data: QrCodeGenerateData, options?: QrCodeGenerateSvgOptions): string;
export { QrCodeDataType, QrCodeGenerateData, QrCodeGenerateInvertableOptions, QrCodeGenerateOptions, QrCodeGenerateResult, QrCodeGenerateSvgOptions, QrCodeGenerateUnicodeOptions, encode, renderANSI, renderSVG, renderUnicode, renderUnicodeCompact };

740
Frontend-Learner/node_modules/uqr/dist/index.mjs generated vendored Normal file
View file

@ -0,0 +1,740 @@
var QrCodeDataType = /* @__PURE__ */ ((QrCodeDataType2) => {
QrCodeDataType2[QrCodeDataType2["Border"] = -1] = "Border";
QrCodeDataType2[QrCodeDataType2["Data"] = 0] = "Data";
QrCodeDataType2[QrCodeDataType2["Function"] = 1] = "Function";
QrCodeDataType2[QrCodeDataType2["Position"] = 2] = "Position";
QrCodeDataType2[QrCodeDataType2["Timing"] = 3] = "Timing";
QrCodeDataType2[QrCodeDataType2["Alignment"] = 4] = "Alignment";
return QrCodeDataType2;
})(QrCodeDataType || {});
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
const LOW = [0, 1];
const MEDIUM = [1, 0];
const QUARTILE = [2, 3];
const HIGH = [3, 2];
const EccMap = {
L: LOW,
M: MEDIUM,
Q: QUARTILE,
H: HIGH
};
const NUMERIC_REGEX = /^[0-9]*$/;
const ALPHANUMERIC_REGEX = /^[A-Z0-9 $%*+.\/:-]*$/;
const ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
const MIN_VERSION = 1;
const MAX_VERSION = 40;
const PENALTY_N1 = 3;
const PENALTY_N2 = 3;
const PENALTY_N3 = 40;
const PENALTY_N4 = 10;
const ECC_CODEWORDS_PER_BLOCK = [
// Version: (note that index 0 is for padding, and is set to an illegal value)
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
[-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],
// Low
[-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],
// Medium
[-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],
// Quartile
[-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]
// High
];
const NUM_ERROR_CORRECTION_BLOCKS = [
// Version: (note that index 0 is for padding, and is set to an illegal value)
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
[-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],
// Low
[-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],
// Medium
[-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],
// Quartile
[-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]
// High
];
class QrCode {
/* -- Constructor (low level) and fields -- */
// Creates a new QR Code with the given version number,
// error correction level, data codeword bytes, and mask number.
// This is a low-level API that most users should not use directly.
// A mid-level API is the encodeSegments() function.
constructor(version, ecc, dataCodewords, msk) {
this.version = version;
this.ecc = ecc;
/* -- Fields -- */
// The width and height of this QR Code, measured in modules, between
// 21 and 177 (inclusive). This is equal to version * 4 + 17.
__publicField(this, "size");
// The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive).
// Even if a QR Code is created with automatic masking requested (mask = -1),
// the resulting object still has a mask value between 0 and 7.
__publicField(this, "mask");
// The modules of this QR Code (false = light, true = dark).
// Immutable after constructor finishes. Accessed through getModule().
__publicField(this, "modules", []);
__publicField(this, "types", []);
if (version < MIN_VERSION || version > MAX_VERSION)
throw new RangeError("Version value out of range");
if (msk < -1 || msk > 7)
throw new RangeError("Mask value out of range");
this.size = version * 4 + 17;
const row = Array.from({ length: this.size }, () => false);
for (let i = 0; i < this.size; i++) {
this.modules.push(row.slice());
this.types.push(row.map(() => 0));
}
this.drawFunctionPatterns();
const allCodewords = this.addEccAndInterleave(dataCodewords);
this.drawCodewords(allCodewords);
if (msk === -1) {
let minPenalty = 1e9;
for (let i = 0; i < 8; i++) {
this.applyMask(i);
this.drawFormatBits(i);
const penalty = this.getPenaltyScore();
if (penalty < minPenalty) {
msk = i;
minPenalty = penalty;
}
this.applyMask(i);
}
}
this.mask = msk;
this.applyMask(msk);
this.drawFormatBits(msk);
}
/* -- Accessor methods -- */
// Returns the color of the module (pixel) at the given coordinates, which is false
// for light or true for dark. The top left corner has the coordinates (x=0, y=0).
// If the given coordinates are out of bounds, then false (light) is returned.
getModule(x, y) {
return x >= 0 && x < this.size && y >= 0 && y < this.size && this.modules[y][x];
}
/* -- Private helper methods for constructor: Drawing function modules -- */
// Reads this object's version field, and draws and marks all function modules.
drawFunctionPatterns() {
for (let i = 0; i < this.size; i++) {
this.setFunctionModule(6, i, i % 2 === 0, QrCodeDataType.Timing);
this.setFunctionModule(i, 6, i % 2 === 0, QrCodeDataType.Timing);
}
this.drawFinderPattern(3, 3);
this.drawFinderPattern(this.size - 4, 3);
this.drawFinderPattern(3, this.size - 4);
const alignPatPos = this.getAlignmentPatternPositions();
const numAlign = alignPatPos.length;
for (let i = 0; i < numAlign; i++) {
for (let j = 0; j < numAlign; j++) {
if (!(i === 0 && j === 0 || i === 0 && j === numAlign - 1 || i === numAlign - 1 && j === 0))
this.drawAlignmentPattern(alignPatPos[i], alignPatPos[j]);
}
}
this.drawFormatBits(0);
this.drawVersion();
}
// Draws two copies of the format bits (with its own error correction code)
// based on the given mask and this object's error correction level field.
drawFormatBits(mask) {
const data = this.ecc[1] << 3 | mask;
let rem = data;
for (let i = 0; i < 10; i++)
rem = rem << 1 ^ (rem >>> 9) * 1335;
const bits = (data << 10 | rem) ^ 21522;
for (let i = 0; i <= 5; i++)
this.setFunctionModule(8, i, getBit(bits, i));
this.setFunctionModule(8, 7, getBit(bits, 6));
this.setFunctionModule(8, 8, getBit(bits, 7));
this.setFunctionModule(7, 8, getBit(bits, 8));
for (let i = 9; i < 15; i++)
this.setFunctionModule(14 - i, 8, getBit(bits, i));
for (let i = 0; i < 8; i++)
this.setFunctionModule(this.size - 1 - i, 8, getBit(bits, i));
for (let i = 8; i < 15; i++)
this.setFunctionModule(8, this.size - 15 + i, getBit(bits, i));
this.setFunctionModule(8, this.size - 8, true);
}
// Draws two copies of the version bits (with its own error correction code),
// based on this object's version field, iff 7 <= version <= 40.
drawVersion() {
if (this.version < 7)
return;
let rem = this.version;
for (let i = 0; i < 12; i++)
rem = rem << 1 ^ (rem >>> 11) * 7973;
const bits = this.version << 12 | rem;
for (let i = 0; i < 18; i++) {
const color = getBit(bits, i);
const a = this.size - 11 + i % 3;
const b = Math.floor(i / 3);
this.setFunctionModule(a, b, color);
this.setFunctionModule(b, a, color);
}
}
// Draws a 9*9 finder pattern including the border separator,
// with the center module at (x, y). Modules can be out of bounds.
drawFinderPattern(x, y) {
for (let dy = -4; dy <= 4; dy++) {
for (let dx = -4; dx <= 4; dx++) {
const dist = Math.max(Math.abs(dx), Math.abs(dy));
const xx = x + dx;
const yy = y + dy;
if (xx >= 0 && xx < this.size && yy >= 0 && yy < this.size)
this.setFunctionModule(xx, yy, dist !== 2 && dist !== 4, QrCodeDataType.Position);
}
}
}
// Draws a 5*5 alignment pattern, with the center module
// at (x, y). All modules must be in bounds.
drawAlignmentPattern(x, y) {
for (let dy = -2; dy <= 2; dy++) {
for (let dx = -2; dx <= 2; dx++) {
this.setFunctionModule(
x + dx,
y + dy,
Math.max(Math.abs(dx), Math.abs(dy)) !== 1,
QrCodeDataType.Alignment
);
}
}
}
// Sets the color of a module and marks it as a function module.
// Only used by the constructor. Coordinates must be in bounds.
setFunctionModule(x, y, isDark, type = QrCodeDataType.Function) {
this.modules[y][x] = isDark;
this.types[y][x] = type;
}
/* -- Private helper methods for constructor: Codewords and masking -- */
// Returns a new byte string representing the given data with the appropriate error correction
// codewords appended to it, based on this object's version and error correction level.
addEccAndInterleave(data) {
const ver = this.version;
const ecl = this.ecc;
if (data.length !== getNumDataCodewords(ver, ecl))
throw new RangeError("Invalid argument");
const numBlocks = NUM_ERROR_CORRECTION_BLOCKS[ecl[0]][ver];
const blockEccLen = ECC_CODEWORDS_PER_BLOCK[ecl[0]][ver];
const rawCodewords = Math.floor(getNumRawDataModules(ver) / 8);
const numShortBlocks = numBlocks - rawCodewords % numBlocks;
const shortBlockLen = Math.floor(rawCodewords / numBlocks);
const blocks = [];
const rsDiv = reedSolomonComputeDivisor(blockEccLen);
for (let i = 0, k = 0; i < numBlocks; i++) {
const dat = data.slice(k, k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1));
k += dat.length;
const ecc = reedSolomonComputeRemainder(dat, rsDiv);
if (i < numShortBlocks)
dat.push(0);
blocks.push(dat.concat(ecc));
}
const result = [];
for (let i = 0; i < blocks[0].length; i++) {
blocks.forEach((block, j) => {
if (i !== shortBlockLen - blockEccLen || j >= numShortBlocks)
result.push(block[i]);
});
}
return result;
}
// Draws the given sequence of 8-bit codewords (data and error correction) onto the entire
// data area of this QR Code. Function modules need to be marked off before this is called.
drawCodewords(data) {
if (data.length !== Math.floor(getNumRawDataModules(this.version) / 8))
throw new RangeError("Invalid argument");
let i = 0;
for (let right = this.size - 1; right >= 1; right -= 2) {
if (right === 6)
right = 5;
for (let vert = 0; vert < this.size; vert++) {
for (let j = 0; j < 2; j++) {
const x = right - j;
const upward = (right + 1 & 2) === 0;
const y = upward ? this.size - 1 - vert : vert;
if (!this.types[y][x] && i < data.length * 8) {
this.modules[y][x] = getBit(data[i >>> 3], 7 - (i & 7));
i++;
}
}
}
}
}
// XORs the codeword modules in this QR Code with the given mask pattern.
// The function modules must be marked and the codeword bits must be drawn
// before masking. Due to the arithmetic of XOR, calling applyMask() with
// the same mask value a second time will undo the mask. A final well-formed
// QR Code needs exactly one (not zero, two, etc.) mask applied.
applyMask(mask) {
if (mask < 0 || mask > 7)
throw new RangeError("Mask value out of range");
for (let y = 0; y < this.size; y++) {
for (let x = 0; x < this.size; x++) {
let invert;
switch (mask) {
case 0:
invert = (x + y) % 2 === 0;
break;
case 1:
invert = y % 2 === 0;
break;
case 2:
invert = x % 3 === 0;
break;
case 3:
invert = (x + y) % 3 === 0;
break;
case 4:
invert = (Math.floor(x / 3) + Math.floor(y / 2)) % 2 === 0;
break;
case 5:
invert = x * y % 2 + x * y % 3 === 0;
break;
case 6:
invert = (x * y % 2 + x * y % 3) % 2 === 0;
break;
case 7:
invert = ((x + y) % 2 + x * y % 3) % 2 === 0;
break;
default:
throw new Error("Unreachable");
}
if (!this.types[y][x] && invert)
this.modules[y][x] = !this.modules[y][x];
}
}
}
// Calculates and returns the penalty score based on state of this QR Code's current modules.
// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.
getPenaltyScore() {
let result = 0;
for (let y = 0; y < this.size; y++) {
let runColor = false;
let runX = 0;
const runHistory = [0, 0, 0, 0, 0, 0, 0];
for (let x = 0; x < this.size; x++) {
if (this.modules[y][x] === runColor) {
runX++;
if (runX === 5)
result += PENALTY_N1;
else if (runX > 5)
result++;
} else {
this.finderPenaltyAddHistory(runX, runHistory);
if (!runColor)
result += this.finderPenaltyCountPatterns(runHistory) * PENALTY_N3;
runColor = this.modules[y][x];
runX = 1;
}
}
result += this.finderPenaltyTerminateAndCount(runColor, runX, runHistory) * PENALTY_N3;
}
for (let x = 0; x < this.size; x++) {
let runColor = false;
let runY = 0;
const runHistory = [0, 0, 0, 0, 0, 0, 0];
for (let y = 0; y < this.size; y++) {
if (this.modules[y][x] === runColor) {
runY++;
if (runY === 5)
result += PENALTY_N1;
else if (runY > 5)
result++;
} else {
this.finderPenaltyAddHistory(runY, runHistory);
if (!runColor)
result += this.finderPenaltyCountPatterns(runHistory) * PENALTY_N3;
runColor = this.modules[y][x];
runY = 1;
}
}
result += this.finderPenaltyTerminateAndCount(runColor, runY, runHistory) * PENALTY_N3;
}
for (let y = 0; y < this.size - 1; y++) {
for (let x = 0; x < this.size - 1; x++) {
const color = this.modules[y][x];
if (color === this.modules[y][x + 1] && color === this.modules[y + 1][x] && color === this.modules[y + 1][x + 1])
result += PENALTY_N2;
}
}
let dark = 0;
for (const row of this.modules)
dark = row.reduce((sum, color) => sum + (color ? 1 : 0), dark);
const total = this.size * this.size;
const k = Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1;
result += k * PENALTY_N4;
return result;
}
/* -- Private helper functions -- */
// Returns an ascending list of positions of alignment patterns for this version number.
// Each position is in the range [0,177), and are used on both the x and y axes.
// This could be implemented as lookup table of 40 variable-length lists of integers.
getAlignmentPatternPositions() {
if (this.version === 1) {
return [];
} else {
const numAlign = Math.floor(this.version / 7) + 2;
const step = this.version === 32 ? 26 : Math.ceil((this.version * 4 + 4) / (numAlign * 2 - 2)) * 2;
const result = [6];
for (let pos = this.size - 7; result.length < numAlign; pos -= step)
result.splice(1, 0, pos);
return result;
}
}
// Can only be called immediately after a light run is added, and
// returns either 0, 1, or 2. A helper function for getPenaltyScore().
finderPenaltyCountPatterns(runHistory) {
const n = runHistory[1];
const core = n > 0 && runHistory[2] === n && runHistory[3] === n * 3 && runHistory[4] === n && runHistory[5] === n;
return (core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0) + (core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0);
}
// Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore().
finderPenaltyTerminateAndCount(currentRunColor, currentRunLength, runHistory) {
if (currentRunColor) {
this.finderPenaltyAddHistory(currentRunLength, runHistory);
currentRunLength = 0;
}
currentRunLength += this.size;
this.finderPenaltyAddHistory(currentRunLength, runHistory);
return this.finderPenaltyCountPatterns(runHistory);
}
// Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore().
finderPenaltyAddHistory(currentRunLength, runHistory) {
if (runHistory[0] === 0)
currentRunLength += this.size;
runHistory.pop();
runHistory.unshift(currentRunLength);
}
}
function appendBits(val, len, bb) {
if (len < 0 || len > 31 || val >>> len !== 0)
throw new RangeError("Value out of range");
for (let i = len - 1; i >= 0; i--)
bb.push(val >>> i & 1);
}
function getBit(x, i) {
return (x >>> i & 1) !== 0;
}
class QrSegment {
// Creates a new QR Code segment with the given attributes and data.
// The character count (numChars) must agree with the mode and the bit buffer length,
// but the constraint isn't checked. The given bit buffer is cloned and stored.
constructor(mode, numChars, bitData) {
this.mode = mode;
this.numChars = numChars;
this.bitData = bitData;
if (numChars < 0)
throw new RangeError("Invalid argument");
this.bitData = bitData.slice();
}
/* -- Methods -- */
// Returns a new copy of the data bits of this segment.
getData() {
return this.bitData.slice();
}
}
const MODE_NUMERIC = [1, 10, 12, 14];
const MODE_ALPHANUMERIC = [2, 9, 11, 13];
const MODE_BYTE = [4, 8, 16, 16];
function numCharCountBits(mode, ver) {
return mode[Math.floor((ver + 7) / 17) + 1];
}
function makeBytes(data) {
const bb = [];
for (const b of data)
appendBits(b, 8, bb);
return new QrSegment(MODE_BYTE, data.length, bb);
}
function makeNumeric(digits) {
if (!isNumeric(digits))
throw new RangeError("String contains non-numeric characters");
const bb = [];
for (let i = 0; i < digits.length; ) {
const n = Math.min(digits.length - i, 3);
appendBits(Number.parseInt(digits.substring(i, i + n), 10), n * 3 + 1, bb);
i += n;
}
return new QrSegment(MODE_NUMERIC, digits.length, bb);
}
function makeAlphanumeric(text) {
if (!isAlphanumeric(text))
throw new RangeError("String contains unencodable characters in alphanumeric mode");
const bb = [];
let i;
for (i = 0; i + 2 <= text.length; i += 2) {
let temp = ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45;
temp += ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1));
appendBits(temp, 11, bb);
}
if (i < text.length)
appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6, bb);
return new QrSegment(MODE_ALPHANUMERIC, text.length, bb);
}
function makeSegments(text) {
if (text === "")
return [];
else if (isNumeric(text))
return [makeNumeric(text)];
else if (isAlphanumeric(text))
return [makeAlphanumeric(text)];
else
return [makeBytes(toUtf8ByteArray(text))];
}
function isNumeric(text) {
return NUMERIC_REGEX.test(text);
}
function isAlphanumeric(text) {
return ALPHANUMERIC_REGEX.test(text);
}
function getTotalBits(segs, version) {
let result = 0;
for (const seg of segs) {
const ccbits = numCharCountBits(seg.mode, version);
if (seg.numChars >= 1 << ccbits)
return Number.POSITIVE_INFINITY;
result += 4 + ccbits + seg.bitData.length;
}
return result;
}
function toUtf8ByteArray(str) {
str = encodeURI(str);
const result = [];
for (let i = 0; i < str.length; i++) {
if (str.charAt(i) !== "%") {
result.push(str.charCodeAt(i));
} else {
result.push(Number.parseInt(str.substring(i + 1, i + 3), 16));
i += 2;
}
}
return result;
}
function getNumRawDataModules(ver) {
if (ver < MIN_VERSION || ver > MAX_VERSION)
throw new RangeError("Version number out of range");
let result = (16 * ver + 128) * ver + 64;
if (ver >= 2) {
const numAlign = Math.floor(ver / 7) + 2;
result -= (25 * numAlign - 10) * numAlign - 55;
if (ver >= 7)
result -= 36;
}
return result;
}
function getNumDataCodewords(ver, ecl) {
return Math.floor(getNumRawDataModules(ver) / 8) - ECC_CODEWORDS_PER_BLOCK[ecl[0]][ver] * NUM_ERROR_CORRECTION_BLOCKS[ecl[0]][ver];
}
function reedSolomonComputeDivisor(degree) {
if (degree < 1 || degree > 255)
throw new RangeError("Degree out of range");
const result = [];
for (let i = 0; i < degree - 1; i++)
result.push(0);
result.push(1);
let root = 1;
for (let i = 0; i < degree; i++) {
for (let j = 0; j < result.length; j++) {
result[j] = reedSolomonMultiply(result[j], root);
if (j + 1 < result.length)
result[j] ^= result[j + 1];
}
root = reedSolomonMultiply(root, 2);
}
return result;
}
function reedSolomonComputeRemainder(data, divisor) {
const result = divisor.map((_) => 0);
for (const b of data) {
const factor = b ^ result.shift();
result.push(0);
divisor.forEach((coef, i) => result[i] ^= reedSolomonMultiply(coef, factor));
}
return result;
}
function reedSolomonMultiply(x, y) {
if (x >>> 8 !== 0 || y >>> 8 !== 0)
throw new RangeError("Byte out of range");
let z = 0;
for (let i = 7; i >= 0; i--) {
z = z << 1 ^ (z >>> 7) * 285;
z ^= (y >>> i & 1) * x;
}
return z;
}
function encodeSegments(segs, ecl, minVersion = 1, maxVersion = 40, mask = -1, boostEcl = true) {
if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7)
throw new RangeError("Invalid value");
let version;
let dataUsedBits;
for (version = minVersion; ; version++) {
const dataCapacityBits2 = getNumDataCodewords(version, ecl) * 8;
const usedBits = getTotalBits(segs, version);
if (usedBits <= dataCapacityBits2) {
dataUsedBits = usedBits;
break;
}
if (version >= maxVersion)
throw new RangeError("Data too long");
}
for (const newEcl of [MEDIUM, QUARTILE, HIGH]) {
if (boostEcl && dataUsedBits <= getNumDataCodewords(version, newEcl) * 8)
ecl = newEcl;
}
const bb = [];
for (const seg of segs) {
appendBits(seg.mode[0], 4, bb);
appendBits(seg.numChars, numCharCountBits(seg.mode, version), bb);
for (const b of seg.getData())
bb.push(b);
}
const dataCapacityBits = getNumDataCodewords(version, ecl) * 8;
appendBits(0, Math.min(4, dataCapacityBits - bb.length), bb);
appendBits(0, (8 - bb.length % 8) % 8, bb);
for (let padByte = 236; bb.length < dataCapacityBits; padByte ^= 236 ^ 17)
appendBits(padByte, 8, bb);
const dataCodewords = Array.from({ length: Math.ceil(bb.length / 8) }, () => 0);
bb.forEach((b, i) => dataCodewords[i >>> 3] |= b << 7 - (i & 7));
return new QrCode(version, ecl, dataCodewords, mask);
}
function encode(data, options) {
const {
ecc = "L",
boostEcc = false,
minVersion = 1,
maxVersion = 40,
maskPattern = -1,
border = 1
} = options || {};
const segment = typeof data === "string" ? makeSegments(data) : Array.isArray(data) ? [makeBytes(data)] : void 0;
if (!segment)
throw new Error(`uqr only supports encoding string and binary data, but got: ${typeof data}`);
const qr = encodeSegments(
segment,
EccMap[ecc],
minVersion,
maxVersion,
maskPattern,
boostEcc
);
const result = addBorder({
version: qr.version,
maskPattern: qr.mask,
size: qr.size,
data: qr.modules,
types: qr.types
}, border);
if (options?.invert)
result.data = result.data.map((row) => row.map((mod) => !mod));
options?.onEncoded?.(result);
return result;
}
function addBorder(input, border = 1) {
if (!border)
return input;
const { size } = input;
const newSize = size + border * 2;
input.size = newSize;
input.data.forEach((row) => {
for (let i = 0; i < border; i++) {
row.unshift(false);
row.push(false);
}
});
for (let i = 0; i < border; i++) {
input.data.unshift(Array.from({ length: newSize }, (_) => false));
input.data.push(Array.from({ length: newSize }, (_) => false));
}
const b = QrCodeDataType.Border;
input.types.forEach((row) => {
for (let i = 0; i < border; i++) {
row.unshift(b);
row.push(b);
}
});
for (let i = 0; i < border; i++) {
input.types.unshift(Array.from({ length: newSize }, (_) => b));
input.types.push(Array.from({ length: newSize }, (_) => b));
}
return input;
}
function getDataAt(data, x, y, defaults = false) {
if (x < 0 || y < 0 || x >= data.length || y >= data.length)
return defaults;
return data[y][x];
}
function renderUnicode(data, options = {}) {
const {
whiteChar = "\u2588",
blackChar = "\u2591"
} = options;
const result = encode(data, options);
return result.data.map((row) => {
return row.map((mod) => mod ? blackChar : whiteChar).join("");
}).join("\n");
}
function renderANSI(data, options = {}) {
return renderUnicode(data, {
...options,
blackChar: "\x1B[40m\u3000\x1B[0m",
whiteChar: "\x1B[47m\u3000\x1B[0m"
});
}
function renderUnicodeCompact(data, options = {}) {
const platte = {
WHITE_ALL: "\u2588",
WHITE_BLACK: "\u2580",
BLACK_WHITE: "\u2584",
BLACK_ALL: " "
};
const result = encode(data, options);
const WHITE = false;
const BLACK = true;
const at = (x, y) => getDataAt(result.data, x, y, true);
const lines = [];
let line = "";
for (let row = 0; row < result.size; row += 2) {
for (let col = 0; col < result.size; col++) {
if (at(col, row) === WHITE && at(col, row + 1) === WHITE)
line += platte.WHITE_ALL;
else if (at(col, row) === WHITE && at(col, row + 1) === BLACK)
line += platte.WHITE_BLACK;
else if (at(col, row) === BLACK && at(col, row + 1) === WHITE)
line += platte.BLACK_WHITE;
else
line += platte.BLACK_ALL;
}
lines.push(line);
line = "";
}
return lines.join("\n");
}
function renderSVG(data, options = {}) {
const result = encode(data, options);
const {
pixelSize = 10,
whiteColor = "white",
blackColor = "black"
} = options;
const height = result.size * pixelSize;
const width = result.size * pixelSize;
let svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}">`;
const pathes = [];
for (let row = 0; row < result.size; row++) {
for (let col = 0; col < result.size; col++) {
const x = col * pixelSize;
const y = row * pixelSize;
if (result.data[row][col])
pathes.push(`M${x},${y}h${pixelSize}v${pixelSize}h-${pixelSize}z`);
}
}
svg += `<rect fill="${whiteColor}" width="${width}" height="${height}"/>`;
svg += `<path fill="${blackColor}" d="${pathes.join("")}"/>`;
svg += "</svg>";
return svg;
}
export { QrCodeDataType, encode, renderANSI, renderSVG, renderUnicode, renderUnicodeCompact };

71
Frontend-Learner/node_modules/uqr/package.json generated vendored Normal file
View file

@ -0,0 +1,71 @@
{
"name": "uqr",
"type": "module",
"version": "0.1.2",
"packageManager": "pnpm@8.6.12",
"description": "Generate QR Code universally, in any runtime, to ANSI, Unicode or SVG.",
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
"license": "MIT",
"homepage": "https://github.com/unjs/uqr#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/unjs/uqr.git"
},
"bugs": "https://github.com/unjs/uqr/issues",
"keywords": [],
"sideEffects": false,
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
},
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"./dist/*",
"./dist/index.d.ts"
]
}
},
"files": [
"dist"
],
"scripts": {
"build": "unbuild",
"dev": "unbuild --stub",
"lint": "eslint .",
"prepublishOnly": "nr build",
"release": "bumpp && npm publish",
"play": "esno play/run.ts",
"test": "vitest",
"typecheck": "tsc --noEmit"
},
"devDependencies": {
"@antfu/eslint-config": "^0.40.2",
"@antfu/ni": "^0.21.5",
"@antfu/utils": "^0.7.6",
"@types/node": "^20.5.0",
"bumpp": "^9.1.1",
"eslint": "^8.47.0",
"esno": "^0.17.0",
"lint-staged": "^14.0.0",
"pnpm": "^8.6.12",
"rimraf": "^5.0.1",
"rollup": "^3.28.0",
"simple-git-hooks": "^2.9.0",
"typescript": "^5.1.6",
"unbuild": "^2.0.0-rc.0",
"vite": "^4.4.9",
"vitest": "^0.34.1"
},
"simple-git-hooks": {
"pre-commit": "pnpm lint-staged"
},
"lint-staged": {
"*": "eslint --fix"
}
}