sculp-js 1.10.0 → 1.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/array.js +18 -1
- package/lib/cjs/async.js +1 -1
- package/lib/cjs/base64.js +1 -1
- package/lib/cjs/clipboard.js +1 -1
- package/lib/cjs/cloneDeep.js +1 -1
- package/lib/cjs/cookie.js +1 -1
- package/lib/cjs/date.js +1 -1
- package/lib/cjs/dom.js +1 -1
- package/lib/cjs/download.js +1 -1
- package/lib/cjs/easing.js +1 -1
- package/lib/cjs/file.js +101 -63
- package/lib/cjs/func.js +1 -1
- package/lib/cjs/index.js +1 -1
- package/lib/cjs/isEqual.js +1 -1
- package/lib/cjs/math.js +1 -1
- package/lib/cjs/number.js +1 -1
- package/lib/cjs/object.js +1 -1
- package/lib/cjs/path.js +1 -1
- package/lib/cjs/qs.js +1 -1
- package/lib/cjs/random.js +1 -1
- package/lib/cjs/string.js +1 -1
- package/lib/cjs/tooltip.js +8 -5
- package/lib/cjs/tree.js +1 -1
- package/lib/cjs/type.js +1 -1
- package/lib/cjs/unique.js +1 -1
- package/lib/cjs/url.js +1 -1
- package/lib/cjs/validator.js +1 -1
- package/lib/cjs/variable.js +1 -1
- package/lib/cjs/watermark.js +1 -1
- package/lib/cjs/we-decode.js +1 -1
- package/lib/es/array.js +18 -1
- package/lib/es/async.js +1 -1
- package/lib/es/base64.js +1 -1
- package/lib/es/clipboard.js +1 -1
- package/lib/es/cloneDeep.js +1 -1
- package/lib/es/cookie.js +1 -1
- package/lib/es/date.js +1 -1
- package/lib/es/dom.js +1 -1
- package/lib/es/download.js +1 -1
- package/lib/es/easing.js +1 -1
- package/lib/es/file.js +101 -63
- package/lib/es/func.js +1 -1
- package/lib/es/index.js +1 -1
- package/lib/es/isEqual.js +1 -1
- package/lib/es/math.js +1 -1
- package/lib/es/number.js +1 -1
- package/lib/es/object.js +1 -1
- package/lib/es/path.js +1 -1
- package/lib/es/qs.js +1 -1
- package/lib/es/random.js +1 -1
- package/lib/es/string.js +1 -1
- package/lib/es/tooltip.js +8 -5
- package/lib/es/tree.js +1 -1
- package/lib/es/type.js +1 -1
- package/lib/es/unique.js +1 -1
- package/lib/es/url.js +1 -1
- package/lib/es/validator.js +1 -1
- package/lib/es/variable.js +1 -1
- package/lib/es/watermark.js +1 -1
- package/lib/es/we-decode.js +1 -1
- package/lib/index.d.ts +28 -7
- package/lib/umd/index.js +221 -163
- package/package.json +1 -1
package/lib/umd/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.10.
|
|
2
|
+
* sculp-js v1.10.2
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -45,6 +45,23 @@
|
|
|
45
45
|
* @param {ArrayLike<V>} array 数组
|
|
46
46
|
* @param {(val: V, idx: number) => Promise<any>} iterator 支持Promise类型的回调函数
|
|
47
47
|
* @param {boolean} reverse 是否反向遍历
|
|
48
|
+
* @example
|
|
49
|
+
* 使用范例如下:
|
|
50
|
+
* const start = async () => {
|
|
51
|
+
* await arrayEachAsync(result, async (item) => {
|
|
52
|
+
* await request(item);
|
|
53
|
+
* count++;
|
|
54
|
+
* })
|
|
55
|
+
* console.log('发送次数', count);
|
|
56
|
+
* }
|
|
57
|
+
|
|
58
|
+
* for await...of 使用范例如下
|
|
59
|
+
* const loadImages = async (images) => {
|
|
60
|
+
* for await (const item of images) {
|
|
61
|
+
* await request(item);
|
|
62
|
+
* count++;
|
|
63
|
+
* }
|
|
64
|
+
* }
|
|
48
65
|
*/
|
|
49
66
|
async function arrayEachAsync(array, iterator, reverse = false) {
|
|
50
67
|
if (reverse) {
|
|
@@ -1360,103 +1377,6 @@
|
|
|
1360
1377
|
});
|
|
1361
1378
|
}
|
|
1362
1379
|
|
|
1363
|
-
const b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
|
1364
|
-
// eslint-disable-next-line
|
|
1365
|
-
const b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
|
|
1366
|
-
/**
|
|
1367
|
-
* 字符串编码成Base64, 平替浏览器的btoa, 不包含中文的处理 (适用于任何环境,包括小程序)
|
|
1368
|
-
* @param {string} string
|
|
1369
|
-
* @returns {string}
|
|
1370
|
-
*/
|
|
1371
|
-
function weBtoa(string) {
|
|
1372
|
-
// 同window.btoa: 字符串编码成Base64
|
|
1373
|
-
string = String(string);
|
|
1374
|
-
let bitmap, a, b, c, result = '', i = 0;
|
|
1375
|
-
const strLen = string.length;
|
|
1376
|
-
const rest = strLen % 3;
|
|
1377
|
-
for (; i < strLen;) {
|
|
1378
|
-
if ((a = string.charCodeAt(i++)) > 255 || (b = string.charCodeAt(i++)) > 255 || (c = string.charCodeAt(i++)) > 255)
|
|
1379
|
-
throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.");
|
|
1380
|
-
bitmap = (a << 16) | (b << 8) | c;
|
|
1381
|
-
result +=
|
|
1382
|
-
b64.charAt((bitmap >> 18) & 63) +
|
|
1383
|
-
b64.charAt((bitmap >> 12) & 63) +
|
|
1384
|
-
b64.charAt((bitmap >> 6) & 63) +
|
|
1385
|
-
b64.charAt(bitmap & 63);
|
|
1386
|
-
}
|
|
1387
|
-
return rest ? result.slice(0, rest - 3) + '==='.substring(rest) : result;
|
|
1388
|
-
}
|
|
1389
|
-
/**
|
|
1390
|
-
* Base64解码为原始字符串,平替浏览器的atob, 不包含中文的处理(适用于任何环境,包括小程序)
|
|
1391
|
-
* @param {string} string
|
|
1392
|
-
* @returns {string}
|
|
1393
|
-
*/
|
|
1394
|
-
function weAtob(string) {
|
|
1395
|
-
// 同window.atob: Base64解码为原始字符串
|
|
1396
|
-
string = String(string).replace(/[\t\n\f\r ]+/g, '');
|
|
1397
|
-
if (!b64re.test(string))
|
|
1398
|
-
throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.");
|
|
1399
|
-
string += '=='.slice(2 - (string.length & 3));
|
|
1400
|
-
let bitmap, result = '', r1, r2, i = 0;
|
|
1401
|
-
for (const strLen = string.length; i < strLen;) {
|
|
1402
|
-
bitmap =
|
|
1403
|
-
(b64.indexOf(string.charAt(i++)) << 18) |
|
|
1404
|
-
(b64.indexOf(string.charAt(i++)) << 12) |
|
|
1405
|
-
((r1 = b64.indexOf(string.charAt(i++))) << 6) |
|
|
1406
|
-
(r2 = b64.indexOf(string.charAt(i++)));
|
|
1407
|
-
result +=
|
|
1408
|
-
r1 === 64
|
|
1409
|
-
? String.fromCharCode((bitmap >> 16) & 255)
|
|
1410
|
-
: r2 === 64
|
|
1411
|
-
? String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255)
|
|
1412
|
-
: String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255, bitmap & 255);
|
|
1413
|
-
}
|
|
1414
|
-
return result;
|
|
1415
|
-
}
|
|
1416
|
-
// function b64DecodeUnicode(str) {
|
|
1417
|
-
// return decodeURIComponent(
|
|
1418
|
-
// exports.weAtob(str).replace(/(.)/g, function (p) {
|
|
1419
|
-
// let code = p.charCodeAt(0).toString(16).toUpperCase();
|
|
1420
|
-
// if (code.length < 2) {
|
|
1421
|
-
// code = '0' + code;
|
|
1422
|
-
// }
|
|
1423
|
-
// return '%' + code;
|
|
1424
|
-
// })
|
|
1425
|
-
// );
|
|
1426
|
-
// }
|
|
1427
|
-
// function base64_url_decode(str) {
|
|
1428
|
-
// let output = str.replace(/-/g, '+').replace(/_/g, '/');
|
|
1429
|
-
// switch (output.length % 4) {
|
|
1430
|
-
// case 0:
|
|
1431
|
-
// break;
|
|
1432
|
-
// case 2:
|
|
1433
|
-
// output += '==';
|
|
1434
|
-
// break;
|
|
1435
|
-
// case 3:
|
|
1436
|
-
// output += '=';
|
|
1437
|
-
// break;
|
|
1438
|
-
// default:
|
|
1439
|
-
// throw new Error('Illegal base64url string!');
|
|
1440
|
-
// }
|
|
1441
|
-
// try {
|
|
1442
|
-
// return b64DecodeUnicode(output);
|
|
1443
|
-
// } catch (err) {
|
|
1444
|
-
// return exports.weAtob(output);
|
|
1445
|
-
// }
|
|
1446
|
-
// }
|
|
1447
|
-
// export function weAppJwtDecode(token, options) {
|
|
1448
|
-
// if (typeof token !== 'string') {
|
|
1449
|
-
// throw new Error('Invalid token specified');
|
|
1450
|
-
// }
|
|
1451
|
-
// options = options || {};
|
|
1452
|
-
// const pos = options.header === true ? 0 : 1;
|
|
1453
|
-
// try {
|
|
1454
|
-
// return JSON.parse(base64_url_decode(token.split('.')[pos]));
|
|
1455
|
-
// } catch (e) {
|
|
1456
|
-
// throw new Error('Invalid token specified: ' + (e as Error).message);
|
|
1457
|
-
// }
|
|
1458
|
-
// }
|
|
1459
|
-
|
|
1460
1380
|
/**
|
|
1461
1381
|
* 判断是否支持canvas
|
|
1462
1382
|
* @returns {boolean}
|
|
@@ -1485,38 +1405,111 @@
|
|
|
1485
1405
|
};
|
|
1486
1406
|
return inputObj;
|
|
1487
1407
|
}
|
|
1408
|
+
/**
|
|
1409
|
+
* 计算图片压缩后的尺寸
|
|
1410
|
+
*
|
|
1411
|
+
* @param {number} maxWidth
|
|
1412
|
+
* @param {number} maxHeight
|
|
1413
|
+
* @param {number} originWidth
|
|
1414
|
+
* @param {number} originHeight
|
|
1415
|
+
* @returns {*}
|
|
1416
|
+
*/
|
|
1417
|
+
function calculateSize({ maxWidth, maxHeight, originWidth, originHeight }) {
|
|
1418
|
+
let width = originWidth, height = originHeight;
|
|
1419
|
+
// 图片尺寸超过限制
|
|
1420
|
+
if (originWidth > maxWidth || originHeight > maxHeight) {
|
|
1421
|
+
if (originWidth / originHeight > maxWidth / maxHeight) {
|
|
1422
|
+
// 更宽,按照宽度限定尺寸
|
|
1423
|
+
width = maxWidth;
|
|
1424
|
+
height = Math.round(maxWidth * (originHeight / originWidth));
|
|
1425
|
+
}
|
|
1426
|
+
else {
|
|
1427
|
+
height = maxHeight;
|
|
1428
|
+
width = Math.round(maxHeight * (originWidth / originHeight));
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
return { width, height };
|
|
1432
|
+
}
|
|
1433
|
+
/**
|
|
1434
|
+
* 根据原始图片的不同尺寸计算等比例缩放后的宽高尺寸
|
|
1435
|
+
*
|
|
1436
|
+
* @param {number} sizeKB
|
|
1437
|
+
* @param {number} originWidth
|
|
1438
|
+
* @param {number} originHeight
|
|
1439
|
+
* @returns {*}
|
|
1440
|
+
*/
|
|
1441
|
+
function scalingByAspectRatio({ sizeKB, originWidth, originHeight }) {
|
|
1442
|
+
let targetWidth = originWidth, targetHeight = originHeight;
|
|
1443
|
+
if (sizeKB <= 500) {
|
|
1444
|
+
// [50KB, 500KB]
|
|
1445
|
+
const maxWidth = 1200, maxHeight = 1200;
|
|
1446
|
+
const { width, height } = calculateSize({ maxWidth, maxHeight, originWidth, originHeight });
|
|
1447
|
+
targetWidth = width;
|
|
1448
|
+
targetHeight = height;
|
|
1449
|
+
}
|
|
1450
|
+
else if (sizeKB < 10 * 1024) {
|
|
1451
|
+
// (500KB, 10MB)
|
|
1452
|
+
const maxWidth = 1600, maxHeight = 1600;
|
|
1453
|
+
const { width, height } = calculateSize({ maxWidth, maxHeight, originWidth, originHeight });
|
|
1454
|
+
targetWidth = width;
|
|
1455
|
+
targetHeight = height;
|
|
1456
|
+
}
|
|
1457
|
+
else if (10 * 1024 <= sizeKB) {
|
|
1458
|
+
// [10MB, Infinity)
|
|
1459
|
+
const maxWidth = originWidth > 15000 ? 8192 : originWidth > 10000 ? 4096 : 2048, maxHeight = originHeight > 15000 ? 8192 : originHeight > 10000 ? 4096 : 2048;
|
|
1460
|
+
const { width, height } = calculateSize({ maxWidth, maxHeight, originWidth, originHeight });
|
|
1461
|
+
targetWidth = width;
|
|
1462
|
+
targetHeight = height;
|
|
1463
|
+
}
|
|
1464
|
+
return { width: targetWidth, height: targetHeight };
|
|
1465
|
+
}
|
|
1488
1466
|
/**
|
|
1489
1467
|
* Web端:等比例压缩图片批量处理 (size小于200KB,不压缩)
|
|
1490
|
-
*
|
|
1491
|
-
* @param {
|
|
1468
|
+
*
|
|
1469
|
+
* @param {File | FileList} file 图片或图片数组
|
|
1470
|
+
* @param {ICompressOptions} options 压缩图片配置项,default: {mime:'image/jpeg'}
|
|
1492
1471
|
* @returns {Promise<object> | undefined}
|
|
1493
1472
|
*/
|
|
1494
|
-
function compressImg(file, options) {
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
if (
|
|
1473
|
+
function compressImg(file, options = { mime: 'image/jpeg' }) {
|
|
1474
|
+
if (!(file instanceof File || file instanceof FileList)) {
|
|
1475
|
+
throw new Error(`${file} require be File or FileList`);
|
|
1476
|
+
}
|
|
1477
|
+
else if (!supportCanvas()) {
|
|
1478
|
+
throw new Error(`Current runtime environment not support Canvas`);
|
|
1479
|
+
}
|
|
1480
|
+
const { quality, mime = 'image/jpeg' } = isObject(options) ? options : {};
|
|
1481
|
+
let targetQuality = quality;
|
|
1482
|
+
if (quality) {
|
|
1483
|
+
targetQuality = quality;
|
|
1484
|
+
}
|
|
1485
|
+
else if (file instanceof File) {
|
|
1499
1486
|
const sizeKB = +parseInt((file.size / 1024).toFixed(2));
|
|
1500
|
-
if (sizeKB < 1 *
|
|
1487
|
+
if (sizeKB < 1 * 50) {
|
|
1488
|
+
targetQuality = 1;
|
|
1489
|
+
}
|
|
1490
|
+
else if (sizeKB < 1 * 1024) {
|
|
1501
1491
|
targetQuality = 0.85;
|
|
1502
1492
|
}
|
|
1503
|
-
else if (sizeKB
|
|
1504
|
-
targetQuality = 0.
|
|
1493
|
+
else if (sizeKB < 5 * 1024) {
|
|
1494
|
+
targetQuality = 0.8;
|
|
1505
1495
|
}
|
|
1506
|
-
else
|
|
1507
|
-
targetQuality = 0.
|
|
1496
|
+
else {
|
|
1497
|
+
targetQuality = 0.75;
|
|
1508
1498
|
}
|
|
1509
1499
|
}
|
|
1510
|
-
if (options.quality) {
|
|
1511
|
-
targetQuality = options.quality;
|
|
1512
|
-
}
|
|
1513
1500
|
if (file instanceof FileList) {
|
|
1514
|
-
return Promise.all(Array.from(file).map(el => compressImg(el, { mime:
|
|
1501
|
+
return Promise.all(Array.from(file).map(el => compressImg(el, { mime: mime, quality: targetQuality }))); // 如果是 file 数组返回 Promise 数组
|
|
1515
1502
|
}
|
|
1516
1503
|
else if (file instanceof File) {
|
|
1517
1504
|
return new Promise(resolve => {
|
|
1505
|
+
const ext = {
|
|
1506
|
+
'image/webp': 'webp',
|
|
1507
|
+
'image/jpeg': 'jpg',
|
|
1508
|
+
'image/png': 'png'
|
|
1509
|
+
};
|
|
1510
|
+
const fileName = [...file.name.split('.').slice(0, -1), ext[mime]].join('.');
|
|
1518
1511
|
const sizeKB = +parseInt((file.size / 1024).toFixed(2));
|
|
1519
|
-
if (+(file.size / 1024).toFixed(2) <
|
|
1512
|
+
if (+(file.size / 1024).toFixed(2) < 50) {
|
|
1520
1513
|
resolve({
|
|
1521
1514
|
file: file
|
|
1522
1515
|
});
|
|
@@ -1529,57 +1522,22 @@
|
|
|
1529
1522
|
image.onload = () => {
|
|
1530
1523
|
const canvas = document.createElement('canvas'); // 创建 canvas 元素
|
|
1531
1524
|
const context = canvas.getContext('2d');
|
|
1532
|
-
let targetWidth = image.width;
|
|
1533
|
-
let targetHeight = image.height;
|
|
1534
1525
|
const originWidth = image.width;
|
|
1535
1526
|
const originHeight = image.height;
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
// 更宽,按照宽度限定尺寸
|
|
1544
|
-
targetWidth = maxWidth;
|
|
1545
|
-
targetHeight = Math.round(maxWidth * (originHeight / originWidth));
|
|
1546
|
-
}
|
|
1547
|
-
else {
|
|
1548
|
-
targetHeight = maxHeight;
|
|
1549
|
-
targetWidth = Math.round(maxHeight * (originWidth / originHeight));
|
|
1550
|
-
}
|
|
1551
|
-
}
|
|
1552
|
-
}
|
|
1553
|
-
if (10 * 1024 <= sizeKB && sizeKB <= 20 * 1024) {
|
|
1554
|
-
const maxWidth = 1400, maxHeight = 1400;
|
|
1555
|
-
targetWidth = originWidth;
|
|
1556
|
-
targetHeight = originHeight;
|
|
1557
|
-
// 图片尺寸超过的限制
|
|
1558
|
-
if (originWidth > maxWidth || originHeight > maxHeight) {
|
|
1559
|
-
if (originWidth / originHeight > maxWidth / maxHeight) {
|
|
1560
|
-
// 更宽,按照宽度限定尺寸
|
|
1561
|
-
targetWidth = maxWidth;
|
|
1562
|
-
targetHeight = Math.round(maxWidth * (originHeight / originWidth));
|
|
1563
|
-
}
|
|
1564
|
-
else {
|
|
1565
|
-
targetHeight = maxHeight;
|
|
1566
|
-
targetWidth = Math.round(maxHeight * (originWidth / originHeight));
|
|
1567
|
-
}
|
|
1568
|
-
}
|
|
1569
|
-
}
|
|
1570
|
-
canvas.width = targetWidth;
|
|
1571
|
-
canvas.height = targetHeight;
|
|
1572
|
-
context.clearRect(0, 0, targetWidth, targetHeight);
|
|
1573
|
-
context.drawImage(image, 0, 0, targetWidth, targetHeight); // 绘制 canvas
|
|
1574
|
-
const canvasURL = canvas.toDataURL(options.mime, targetQuality);
|
|
1575
|
-
const buffer = weAtob(canvasURL.split(',')[1]);
|
|
1527
|
+
const { width, height } = scalingByAspectRatio({ sizeKB, originWidth, originHeight });
|
|
1528
|
+
canvas.width = width;
|
|
1529
|
+
canvas.height = height;
|
|
1530
|
+
context.clearRect(0, 0, width, height);
|
|
1531
|
+
context.drawImage(image, 0, 0, width, height); // 绘制 canvas
|
|
1532
|
+
const canvasURL = canvas.toDataURL(mime, targetQuality);
|
|
1533
|
+
const buffer = atob(canvasURL.split(',')[1]);
|
|
1576
1534
|
let length = buffer.length;
|
|
1577
1535
|
const bufferArray = new Uint8Array(new ArrayBuffer(length));
|
|
1578
1536
|
while (length--) {
|
|
1579
1537
|
bufferArray[length] = buffer.charCodeAt(length);
|
|
1580
1538
|
}
|
|
1581
|
-
const miniFile = new File([bufferArray],
|
|
1582
|
-
type:
|
|
1539
|
+
const miniFile = new File([bufferArray], fileName, {
|
|
1540
|
+
type: mime
|
|
1583
1541
|
});
|
|
1584
1542
|
resolve({
|
|
1585
1543
|
file: miniFile,
|
|
@@ -2032,16 +1990,19 @@
|
|
|
2032
1990
|
};
|
|
2033
1991
|
|
|
2034
1992
|
/**
|
|
2035
|
-
*
|
|
1993
|
+
* 自定义的 tooltip, 支持鼠标移动动悬浮提示
|
|
2036
1994
|
* @Desc 自定义的tooltip方法, 支持拖动悬浮提示
|
|
2037
1995
|
* Created by chendeqiao on 2017/5/8.
|
|
2038
1996
|
* @example
|
|
2039
|
-
* <span onmouseleave="handleMouseLeave('#root')"
|
|
2040
|
-
*
|
|
1997
|
+
* <span onmouseleave="handleMouseLeave('#root')"
|
|
1998
|
+
* onmousemove="handleMouseEnter({rootContainer: '#root', title: 'title content', event: event})"
|
|
1999
|
+
* onmouseenter="handleMouseEnter({rootContainer:'#root', title: 'title content', event: event})">
|
|
2000
|
+
* title content
|
|
2001
|
+
* </span>
|
|
2041
2002
|
*/
|
|
2042
2003
|
/**
|
|
2043
2004
|
* 自定义title提示功能的mouseenter事件句柄
|
|
2044
|
-
* @param {ITooltipParams}
|
|
2005
|
+
* @param {ITooltipParams} param
|
|
2045
2006
|
* @returns {*}
|
|
2046
2007
|
*/
|
|
2047
2008
|
function handleMouseEnter({ rootContainer = '#root', title, event, bgColor = '#000', color = '#fff' }) {
|
|
@@ -2494,6 +2455,103 @@
|
|
|
2494
2455
|
return +parseFloat(Number(num).toPrecision(precision));
|
|
2495
2456
|
}
|
|
2496
2457
|
|
|
2458
|
+
const b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
|
2459
|
+
// eslint-disable-next-line
|
|
2460
|
+
const b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
|
|
2461
|
+
/**
|
|
2462
|
+
* 字符串编码成Base64, 平替浏览器的btoa, 不包含中文的处理 (适用于任何环境,包括小程序)
|
|
2463
|
+
* @param {string} string
|
|
2464
|
+
* @returns {string}
|
|
2465
|
+
*/
|
|
2466
|
+
function weBtoa(string) {
|
|
2467
|
+
// 同window.btoa: 字符串编码成Base64
|
|
2468
|
+
string = String(string);
|
|
2469
|
+
let bitmap, a, b, c, result = '', i = 0;
|
|
2470
|
+
const strLen = string.length;
|
|
2471
|
+
const rest = strLen % 3;
|
|
2472
|
+
for (; i < strLen;) {
|
|
2473
|
+
if ((a = string.charCodeAt(i++)) > 255 || (b = string.charCodeAt(i++)) > 255 || (c = string.charCodeAt(i++)) > 255)
|
|
2474
|
+
throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.");
|
|
2475
|
+
bitmap = (a << 16) | (b << 8) | c;
|
|
2476
|
+
result +=
|
|
2477
|
+
b64.charAt((bitmap >> 18) & 63) +
|
|
2478
|
+
b64.charAt((bitmap >> 12) & 63) +
|
|
2479
|
+
b64.charAt((bitmap >> 6) & 63) +
|
|
2480
|
+
b64.charAt(bitmap & 63);
|
|
2481
|
+
}
|
|
2482
|
+
return rest ? result.slice(0, rest - 3) + '==='.substring(rest) : result;
|
|
2483
|
+
}
|
|
2484
|
+
/**
|
|
2485
|
+
* Base64解码为原始字符串,平替浏览器的atob, 不包含中文的处理(适用于任何环境,包括小程序)
|
|
2486
|
+
* @param {string} string
|
|
2487
|
+
* @returns {string}
|
|
2488
|
+
*/
|
|
2489
|
+
function weAtob(string) {
|
|
2490
|
+
// 同window.atob: Base64解码为原始字符串
|
|
2491
|
+
string = String(string).replace(/[\t\n\f\r ]+/g, '');
|
|
2492
|
+
if (!b64re.test(string))
|
|
2493
|
+
throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.");
|
|
2494
|
+
string += '=='.slice(2 - (string.length & 3));
|
|
2495
|
+
let bitmap, result = '', r1, r2, i = 0;
|
|
2496
|
+
for (const strLen = string.length; i < strLen;) {
|
|
2497
|
+
bitmap =
|
|
2498
|
+
(b64.indexOf(string.charAt(i++)) << 18) |
|
|
2499
|
+
(b64.indexOf(string.charAt(i++)) << 12) |
|
|
2500
|
+
((r1 = b64.indexOf(string.charAt(i++))) << 6) |
|
|
2501
|
+
(r2 = b64.indexOf(string.charAt(i++)));
|
|
2502
|
+
result +=
|
|
2503
|
+
r1 === 64
|
|
2504
|
+
? String.fromCharCode((bitmap >> 16) & 255)
|
|
2505
|
+
: r2 === 64
|
|
2506
|
+
? String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255)
|
|
2507
|
+
: String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255, bitmap & 255);
|
|
2508
|
+
}
|
|
2509
|
+
return result;
|
|
2510
|
+
}
|
|
2511
|
+
// function b64DecodeUnicode(str) {
|
|
2512
|
+
// return decodeURIComponent(
|
|
2513
|
+
// exports.weAtob(str).replace(/(.)/g, function (p) {
|
|
2514
|
+
// let code = p.charCodeAt(0).toString(16).toUpperCase();
|
|
2515
|
+
// if (code.length < 2) {
|
|
2516
|
+
// code = '0' + code;
|
|
2517
|
+
// }
|
|
2518
|
+
// return '%' + code;
|
|
2519
|
+
// })
|
|
2520
|
+
// );
|
|
2521
|
+
// }
|
|
2522
|
+
// function base64_url_decode(str) {
|
|
2523
|
+
// let output = str.replace(/-/g, '+').replace(/_/g, '/');
|
|
2524
|
+
// switch (output.length % 4) {
|
|
2525
|
+
// case 0:
|
|
2526
|
+
// break;
|
|
2527
|
+
// case 2:
|
|
2528
|
+
// output += '==';
|
|
2529
|
+
// break;
|
|
2530
|
+
// case 3:
|
|
2531
|
+
// output += '=';
|
|
2532
|
+
// break;
|
|
2533
|
+
// default:
|
|
2534
|
+
// throw new Error('Illegal base64url string!');
|
|
2535
|
+
// }
|
|
2536
|
+
// try {
|
|
2537
|
+
// return b64DecodeUnicode(output);
|
|
2538
|
+
// } catch (err) {
|
|
2539
|
+
// return exports.weAtob(output);
|
|
2540
|
+
// }
|
|
2541
|
+
// }
|
|
2542
|
+
// export function weAppJwtDecode(token, options) {
|
|
2543
|
+
// if (typeof token !== 'string') {
|
|
2544
|
+
// throw new Error('Invalid token specified');
|
|
2545
|
+
// }
|
|
2546
|
+
// options = options || {};
|
|
2547
|
+
// const pos = options.header === true ? 0 : 1;
|
|
2548
|
+
// try {
|
|
2549
|
+
// return JSON.parse(base64_url_decode(token.split('.')[pos]));
|
|
2550
|
+
// } catch (e) {
|
|
2551
|
+
// throw new Error('Invalid token specified: ' + (e as Error).message);
|
|
2552
|
+
// }
|
|
2553
|
+
// }
|
|
2554
|
+
|
|
2497
2555
|
function stringToUint8Array(str) {
|
|
2498
2556
|
const utf8 = encodeURIComponent(str); // 将字符串转换为 UTF-8 编码
|
|
2499
2557
|
const uint8Array = new Uint8Array(utf8.length); // 创建 Uint8Array
|