diff --git a/README.md b/README.md index 56efb5d..333254a 100644 --- a/README.md +++ b/README.md @@ -80,16 +80,28 @@ console.log(validNumber('1.2.')); // 1.20 12. 能用 `const` 定义的地方尽量用 `const`。 13. 不能使用 `var` 定义变量。 14. `不要炫技`,用尽量简单易懂的方式,宁愿多写几行,也不要增加理解难度。 -15. 尽量不要函数引入函数,每个函数尽量独立,不依赖其他函数。 -16. 除导出函数外,其余函数不能使用多行注释,只能使用单行注释。 -17. 一个工具函数的代码行数不超过500行(`特殊情况例外`)。 -18. 代码风格以笔者规范为准(会进行沟通),不能擅自修改代码规范。 -19. 笔者会对所有提交的代码进行审核,并根据情况增删代码。 -20. 如若本项目产生收益,仓库所有者(陈随易)拥有对收益的完全支配权。 -21. 如果提交代码,便视为同意以上守则,请查阅并确认后参与。 +15. `es-toolkit` 和 `lodash` 已经存在的函数不要重复实现。 +16. `只有几行代码` 的函数不要添加进来。 +17. 尽量不要函数引入函数,每个函数尽量独立,不依赖其他函数。 +18. 除导出函数外,其余函数不能使用多行注释,只能使用单行注释。 +19. 一个工具函数的代码行数不超过500行(`特殊情况例外`)。 +20. 代码风格以笔者规范为准(会进行沟通),不能擅自修改代码规范。 +21. 笔者会对所有提交的代码进行审核,并根据情况增删代码。 +22. 如若本项目产生收益,仓库所有者(陈随易)拥有对收益的完全支配权。 +23. 如果提交代码,便视为同意以上守则,请查阅并确认后参与。 ### **函数开发说明** +目前用到的依赖如下: + +1. lodash-es +2. es-toolkit +3. date-fns + +因为es-toolkit还在开发中,所以部分函数用lodash-es中的。 + +最终目标是所有基础函数都用es-toolkit中的。 + `lib` 目录下,每一个目录是一个函数类型集合。 每个目录下,不能再创建目录,只能创建函数文件。 diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..a24dd09 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "baseUrl": "./", + "paths": {} + }, + "exclude": ["**/node_modules/*", "dist", "**/dist/*", "dist", "dist*", "node_modules", "release", "cache", ".git", ".cache", "logs"] +} diff --git a/lib/address/areaMatch.js b/lib/address/areaMatch.js index 1889229..d0ef261 100644 --- a/lib/address/areaMatch.js +++ b/lib/address/areaMatch.js @@ -1,30 +1,26 @@ /** * 省、市、区提取 - * @author 陈随易 - * @category address * @alias yd_address_areaMatch + * @category address * @param {string} address 地址字符串 * @returns {Array} 省市区 + * @author 陈随易 * @example * const address1 = "北京市朝阳区建国门外大街"; * const addressComponents1 = extractAddressComponents(address1); * console.log(addressComponents1); // 输出: { province: '北京', city: '朝阳', region: '建国门外大街' } - * * @example * const address2 = "广东省深圳市南山区科技园"; * const addressComponents2 = extractAddressComponents(address2); * console.log(addressComponents2); // 输出: { province: '广东', city: '深圳', region: '南山区科技园' } - * * @example * const address3 = "上海市浦东新区张江高科技园区"; * const addressComponents3 = extractAddressComponents(address3); * console.log(addressComponents3); // 输出: { province: '上海', city: '浦东新区', region: '张江高科技园区' } - * * @example * const address4 = "黑龙江省哈尔滨市道里区"; * const addressComponents4 = extractAddressComponents(address4); * console.log(addressComponents4); // 输出: { province: '黑龙江', city: '哈尔滨', region: '道里区' } - * * @example * const address5 = "错误地址"; * const addressComponents5 = extractAddressComponents(address5); diff --git a/lib/array/chunk.js b/lib/array/chunk.js deleted file mode 100644 index 12f7786..0000000 --- a/lib/array/chunk.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @description 根据size 返回对应size的二维数组, 如果array 无法被分割成全部等长的区块,那么最后剩余的元素将组成一个区块。 - * @author grantguo - * @category array - * @alias yd_array_chunk - * @param { Array } array - * @param { Number } size - * @param { Boolean } origin 剩余元素是否支持组成一个区块,默认支持 - * @return 返回二维数组 - * @summary 根据size 返回对应size的二维数组 - * @example - * chunk(['a', 'b', 'c', 'd'], 2); - * // => [['a', 'b'], ['c', 'd']] - * - * chunk(['a', 'b', 'c', 'd'], 3); - * // => [['a', 'b', 'c'], ['d']] - * - * chunk(['a', 'b', 'c', 'd', 'e'], 3, false); - * // => [['a', 'b', 'c']] - * - */ - -export default (array, size, origin = true) => { - const intSize = Math.trunc(size); - - if (array.length === 0 || intSize < 1) return []; - - let index = 0; - let resultIndex = 0; - // const result = new Array(Math.ceil(array.length / size)); - const result = new Array(); - - while (index < array.length) { - if (!origin && array.slice(index).length < intSize) { - break; - } - result[resultIndex++] = array.slice(index, (index += intSize)); - } - return result; -}; diff --git a/lib/array/chunk.test.js b/lib/array/chunk.test.js deleted file mode 100644 index 5d521ac..0000000 --- a/lib/array/chunk.test.js +++ /dev/null @@ -1,15 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_array_chunk from './chunk.js'; - -describe('yd_array_chunk', () => { - it('it shoule return a array', () => { - const arr = ['a', 'b', 'c', 'd', 'e']; - const new_arr = yd_array_chunk(arr, 3); - expect(new_arr).toEqual([ - ['a', 'b', 'c'], - ['d', 'e'] - ]); - const new_arr1 = yd_array_chunk(arr, 3, false); - expect(new_arr1).toEqual([['a', 'b', 'c']]); - }); -}); diff --git a/lib/array/concat.js b/lib/array/concat.js deleted file mode 100644 index 36595ee..0000000 --- a/lib/array/concat.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * 合并数组 - * @author 陈随易 - * @category array - * @alias yd_array_concat - * @param {...any} args 多个数组 - * @returns {Array} 多个数组合并值 - */ -export default (...args) => { - // 创建一个新的数组来存储结果 - const result = []; - - // 循环遍历所有参数 - for (let i = 0; i < args.length; i++) { - // 如果参数是数组,则将数组中的每个元素添加到结果数组中 - if (Array.isArray(args[i])) { - for (let j = 0; j < args[i].length; j++) { - result.push(args[i][j]); - } - } else { - // 如果参数不是数组,则直接添加到结果数组中 - result.push(args[i]); - } - } - - // 返回结果数组 - return result; -}; diff --git a/lib/array/filterBy.js b/lib/array/filterBy.js deleted file mode 100644 index 96d93ab..0000000 --- a/lib/array/filterBy.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * 数组按条件过滤 - * @alias yd_array_filterBy - * @category array - * @param {Array} arrs 数组数据 - * @param {Function} fn 比对函数 - * @returns {object} 返回根据字段映射的对象 - * @author 陈随易 - * @example yd_array_filterBy() - */ -export default (arrs, fn) => { - const result = arrs.filter((item) => { - return fn(item); - }); - return result; -}; diff --git a/lib/array/filterBy.test.js b/lib/array/filterBy.test.js deleted file mode 100644 index 56445a1..0000000 --- a/lib/array/filterBy.test.js +++ /dev/null @@ -1,19 +0,0 @@ -import { it, expect, describe } from 'vitest'; -import yd_array_filterBy from './filterBy.js'; - -describe('yd_array_filterBy', () => { - it('应该返回 true', () => { - const arrs = [ - { type: 'food', value: 1 }, - { type: 'book', value: 2 }, - { type: 'book', value: 3 }, - { type: 'food', value: 4 }, - { type: 'book', value: 5 } - ]; - const result = yd_array_filterBy(arrs, (item) => item.type === 'food'); - expect(result).toStrictEqual([ - { type: 'food', value: 1 }, - { type: 'food', value: 4 } - ]); - }); -}); diff --git a/lib/array/findIndex.js b/lib/array/findIndex.js deleted file mode 100644 index 042fd40..0000000 --- a/lib/array/findIndex.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 查找数组中匹配的索引 - * @author 陈随易 - * @category array - * @alias yd_array_findIndex - * @param {Array} array 数组 - * @param {string} field 要查找的字段 - * @param {string} value 该字段的值 - * @returns {number} 返回匹配的索引 - */ -export default (array, field, value) => { - let result = null; - for (const [index, item] of array.entries()) { - for (const prop in item) { - if (Object.prototype.hasOwnProperty.call(item, prop)) { - if (prop === field && item[prop] === value) { - result = index; - break; - } - } - } - } - return result; -}; diff --git a/lib/array/findObj.js b/lib/array/findObj.js deleted file mode 100644 index 189861c..0000000 --- a/lib/array/findObj.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 查找数组中匹配的值 - * @author 陈随易 - * @category array - * @alias yd_array_findObj - * @param {Array} arrObj 数组对象 - * @param {string} field 要查找的属性 - * @param {Any} value 属性的值 - * @returns {object} 返回匹配的对象 - */ -export default (arrObj, field, value) => { - let result = {}; - for (const item of arrObj) { - for (const prop in item) { - if (Object.prototype.hasOwnProperty.call(item, prop)) { - if (prop === field && item[prop] === value) { - result = item; - break; - } - } - } - } - return result; -}; diff --git a/lib/array/flatten.js b/lib/array/flatten.js deleted file mode 100644 index fd9cad8..0000000 --- a/lib/array/flatten.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 将多维数组拍平为一维数组 - * @author WZBBiao - * @category array - * @alias yd_array_flatten - * @param {Array} arr - 需要拍平的数组 - * @returns {Array} - 拍平后的数组 - * @example - * console.log(yd_array_flatten([1, [2, [3, [4]], 5]])); // [1, 2, 3, 4, 5] - */ -export default (arr) => { - const result = []; - const flatten = (arr) => { - arr.forEach((item) => { - if (Array.isArray(item)) { - flatten(item); - } else { - result.push(item); - } - }); - }; - flatten(arr); - return result; -}; diff --git a/lib/array/group.js b/lib/array/group.js deleted file mode 100644 index 838deab..0000000 --- a/lib/array/group.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * 数组数据分组 - * @alias yd_array_group - * @category array - * @param {Array} array 数组 - * @param {string} key 分组的字段或函数 - * @returns {object} 返回按某字段或函数分组后的对象 - * @author 陈随易 - * @example yd_array_group() - */ -export default (array, key) => { - const result = new Map(); - for (const item of array) { - const groupKey = item[key]; - - if (!result.has(groupKey)) { - result.set(groupKey, []); - } - result.get(groupKey).push(item); - } - return result; -}; diff --git a/lib/array/groupBy.js b/lib/array/groupBy.js deleted file mode 100644 index 9b1a49f..0000000 --- a/lib/array/groupBy.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * 数组数据分组 - * @alias yd_array_groupBy - * @category array - * @param {Array} array 数组 - * @param {Function} fun 分组的字段或函数 - * @returns {object} 返回按某字段或函数分组后的对象 - * @author 陈随易 - * @example yd_array_groupBy() - */ -export default (array, fun) => { - const result = new Map(); - for (const item of array) { - const groupKey = fun(item); - if (!result.has(groupKey)) { - result.set(groupKey, []); - } - result.get(groupKey).push(item); - } - return result; -}; diff --git a/lib/array/intersection.js b/lib/array/intersection.js deleted file mode 100644 index 2e82cfe..0000000 --- a/lib/array/intersection.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @alias yd_array_intersection - * @category array - * @param {Array} array1 - 第一个数组。 - * @param {Array} array2 - 第二个数组。 - * @returns {Array} - 包含两个数组交集的数组。 - * @author penn - * @example - * console.log(arrayIntersection([1, 2, 3], [2, 3, 4])) - * // 输出: [2, 3] - * @description 计算两个数组的交集。 - */ -export default function arrayIntersection(array1, array2) { - if (!Array.isArray(array1) || !Array.isArray(array2)) { - throw new TypeError('Both arguments must be arrays'); - } - - const set2 = new Set(array2); - const intersectionElements = array1.filter((element) => set2.has(element)); - return Array.from(new Set(intersectionElements)); // unique -} diff --git a/lib/array/intersection.test.js b/lib/array/intersection.test.js deleted file mode 100644 index 646a516..0000000 --- a/lib/array/intersection.test.js +++ /dev/null @@ -1,38 +0,0 @@ -import { it, expect, describe } from 'vitest'; -import yd_array_intersection from './intersection.js'; - -describe('yd_array_intersection', () => { - it('should return the correct intersection of two arrays', () => { - const result = yd_array_intersection([1, 2, 3], [2, 3, 4]); - expect(result).toEqual([2, 3]); - }); - - it('should return an empty array when there are no common elements', () => { - const result = yd_array_intersection([1, 2, 3], [4, 5, 6]); - expect(result).toEqual([]); - }); - - it('should return the correct intersection when one array is empty', () => { - const result = yd_array_intersection([1, 2, 3], []); - expect(result).toEqual([]); - }); - - it('should return the correct intersection when both arrays are empty', () => { - const result = yd_array_intersection([], []); - expect(result).toEqual([]); - }); - - it('should return the correct intersection with mixed data types', () => { - const result = yd_array_intersection([1, 'a', 3], [3, 'a', 5]); - expect(result).toEqual(['a', 3]); - }); - - it('should return unique values in the intersection', () => { - const result = yd_array_intersection([1, 2, 2, 3], [2, 2, 4]); - expect(result).toEqual([2]); - }); - - it('should throw an error if the second argument is not an array', () => { - expect(() => yd_array_intersection([1, 2, 3], 'not an array')).toThrow(TypeError); - }); -}); diff --git a/lib/array/keyBy.js b/lib/array/keyBy.js deleted file mode 100644 index eb6628b..0000000 --- a/lib/array/keyBy.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * 数组按key排序 - * @author 陈随易 - * @category array - * @alias yd_array_keyBy - * @param {Array} array 数组 - * @param {string} field 映射字段 - * @returns {object} 返回根据字段映射的对象 - */ -export default (array, field) => { - const result = {}; - array.forEach((item) => { - result[item[field]] = item; - }); - return result; -}; diff --git a/lib/array/max.js b/lib/array/max.js deleted file mode 100644 index ce6ef0c..0000000 --- a/lib/array/max.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @alias yd_array_max - * @category array - * @param {Array} array - 输入的数组。 - * @returns {number} - 数组中的最大值。 - * @author penn - * @example - * console.log(arrayMax([1, 2, 3, 4, 5])) - * // 输出: 5 - * @description 计算数组中的最大值。 - */ -export default (array) => { - try { - return Math.max(...array); - } catch (error) { - throw new TypeError('An error occurred: ' + error.message); - } -}; diff --git a/lib/array/max.test.js b/lib/array/max.test.js deleted file mode 100644 index 811c10b..0000000 --- a/lib/array/max.test.js +++ /dev/null @@ -1,25 +0,0 @@ -import { it, expect, describe } from 'vitest'; -import yd_array_max from './max.js'; - -describe('yd_array_max', () => { - it('should return the max value in the array', () => { - const arr = [1, 2, 3, 4, 5]; - const result = yd_array_max(arr); - expect(result).toBe(5); - }); - - it('should return NaN if the array contains non-number element', () => { - const arr1 = [6, 2, 3, '1', 5]; - const arr2 = [1, 2, 3, 'a', 5]; - const result1 = yd_array_max(arr1); - const result2 = yd_array_max(arr2); - expect(result1).toBe(6); - expect(result2).toBeNaN(); - }); - - it('should return Infinity if the array is empty', () => { - const arr = []; - const result = yd_array_max(arr); - expect(result).toBe(-Infinity); - }); -}); diff --git a/lib/array/maxBy.js b/lib/array/maxBy.js deleted file mode 100644 index 956e036..0000000 --- a/lib/array/maxBy.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * 根据属性键或访问器函数找到数组中的最大元素 - * @author Amonduul - * @alias yd_array_maxBy - * @category array - * @param {Array} array - 要搜索的数组 - * @param {Function|string} iteratee - 用于提取比较值的函数或属性键 - * @returns {*} 返回数组中具有最大值的元素 - * @throws {Error} 如果提供的数组为空或 iteratee 不是函数或字符串 - */ -export default (array, iteratee) => { - if (!Array.isArray(array) || array.length === 0) { - throw new Error('First argument must be a non-empty array.'); - } - - if (typeof iteratee !== 'function' && typeof iteratee !== 'string') { - throw new Error('Second argument must be a function or a string.'); - } - - let maxElement = array[0]; - let maxValue = typeof iteratee === 'function' ? iteratee(maxElement) : maxElement[iteratee]; - - for (const element of array) { - const value = typeof iteratee === 'function' ? iteratee(element) : element[iteratee]; - if (value > maxValue) { - maxElement = element; - maxValue = value; - } - } - - return maxElement; -}; diff --git a/lib/array/maxBy.test.js b/lib/array/maxBy.test.js deleted file mode 100644 index 8591f1d..0000000 --- a/lib/array/maxBy.test.js +++ /dev/null @@ -1,34 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_array_maxBy from './maxBy.js'; - -describe('yd_array_maxBy', () => { - it('should find the element with the maximum value in an array', () => { - const array = [ - { name: 'Alice', age: 25 }, - { name: 'Bob', age: 30 }, - { name: 'Charlie', age: 20 } - ]; - - const result = yd_array_maxBy(array, 'age'); - expect(result).toEqual({ name: 'Bob', age: 30 }); - }); - - it('should accept a function as the iteratee', () => { - const array = [ - { name: 'Alice', age: 25 }, - { name: 'Bob', age: 30 }, - { name: 'Charlie', age: 20 } - ]; - - const result = yd_array_maxBy(array, (item) => item.age); - expect(result).toEqual({ name: 'Bob', age: 30 }); - }); - - it('should throw an error if the array is empty', () => { - expect(() => yd_array_maxBy([], 'age')).toThrow('First argument must be a non-empty array.'); - }); - - it('should throw an error if the iteratee is not a function or a string', () => { - expect(() => yd_array_maxBy([{ a: 1 }, { a: 2 }], 123)).toThrow('Second argument must be a function or a string.'); - }); -}); diff --git a/lib/array/merge.js b/lib/array/merge.js deleted file mode 100644 index b79391d..0000000 --- a/lib/array/merge.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * 合并多个数组并返回它们的并集 - * @author Amonduul - * @category array - * @alias yd_array_merge - * @param { Array } ...arrays - 可变数量的数组参数 - * @returns { Array } 所有数组的并集 - * @throws { Error } 如果任何一个参数不是数组 - */ -export default (...arrays) => { - // 检查每个参数是否都是数组 - if (!arrays.every(Array.isArray)) { - throw new Error('All arguments must be arrays.'); - } - const unionSet = new Set(); - arrays.forEach((array) => { - array.forEach((item) => { - unionSet.add(item); - }); - }); - return Array.from(unionSet); -}; diff --git a/lib/array/merge.test.js b/lib/array/merge.test.js deleted file mode 100644 index 300770d..0000000 --- a/lib/array/merge.test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_array_merge from './merge.js'; - -describe('yd_array_merge', () => { - it('should merge multiple arrays and return their union', () => { - const arr1 = [1, 2, 3]; - const arr2 = [3, 4, 5]; - const arr3 = [5, 6, 7]; - - expect(yd_array_merge(arr1, arr2, arr3)).toEqual([1, 2, 3, 4, 5, 6, 7]); - }); - - it('should throw an error if any argument is not an array', () => { - expect(() => yd_array_merge([1, 2], 'foo')).toThrow('All arguments must be arrays.'); - }); -}); diff --git a/lib/array/min.js b/lib/array/min.js deleted file mode 100644 index d8fe779..0000000 --- a/lib/array/min.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @alias yd_array_min - * @category array - * @param {Array} array - 输入的数组。 - * @returns {number} - 数组中的最小值。 - * @author penn - * @example - * console.log(arrayMin([1, 2, 3, 4, 5])) - * // 输出: 1 - * @description 计算数组中的最小值 - */ -export default (array) => { - try { - return Math.min(...array); - } catch (error) { - throw new TypeError('An error occurred: ' + error.message); - } -}; diff --git a/lib/array/min.test.js b/lib/array/min.test.js deleted file mode 100644 index 3f7130c..0000000 --- a/lib/array/min.test.js +++ /dev/null @@ -1,25 +0,0 @@ -import { it, expect, describe } from 'vitest'; -import yd_array_min from './min.js'; - -describe('yd_array_min', () => { - it('should return the min value in the array', () => { - const arr = [1, 2, 3, 4, 5]; - const result = yd_array_min(arr); - expect(result).toBe(1); - }); - - it('should return NaN if the array contains non-number element', () => { - const arr1 = [6, 2, 3, '1', 5]; - const arr2 = [1, 2, 3, 'a', 5]; - const result1 = yd_array_min(arr1); - const result2 = yd_array_min(arr2); - expect(result1).toBe(1); - expect(result2).toBeNaN(); - }); - - it('should return Infinity if the array is empty', () => { - const arr = []; - const result = yd_array_min(arr); - expect(result).toBe(Infinity); - }); -}); diff --git a/lib/array/omitBy.js b/lib/array/omitBy.js deleted file mode 100644 index d5480d2..0000000 --- a/lib/array/omitBy.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * 从数组中排除指定标签的项 - * @alias yd_array_omitBy - * @category 数组操作 - * @param {object[]} arry - 需要处理的数组,其中每个对象包含 `label` 和 `value` 属性 - * @param {string[]} keys - 需要排除的标签列表 - * @returns {object[]} 返回一个新数组,其中不包含具有指定标签的项 - * @author 卞雪瑞 - * @summary 这个函数根据给定的标签列表,排除数组中所有匹配这些标签的项,并返回剩余的项。 - * @example - * yd_array_omitBy( - * [{ label: 'a', value: 1 }, { label: 'b', value: 2 }, { label: 'c', value: 3 }], - * ['a', 'c'] - * ); - * 结果: - * [ - * { label: 'b', value: 2 } - * ] - */ -export default (arry, keys) => { - return arry.filter((item) => !keys.includes(item.label)); -}; diff --git a/lib/array/omitBy.test.js b/lib/array/omitBy.test.js deleted file mode 100644 index c9b7ef6..0000000 --- a/lib/array/omitBy.test.js +++ /dev/null @@ -1,58 +0,0 @@ -import yd_array_omitBy from './omitBy.js'; -import { describe, expect, test } from 'vitest'; - -describe('yd_array_omitBy', () => { - test('根据标签排除数组中的项', () => { - const array = [ - { label: 'a', value: 1 }, - { label: 'b', value: 2 }, - { label: 'c', value: 3 } - ]; - const keys = ['a', 'c']; - const result = yd_array_omitBy(array, keys); - expect(result).toEqual([{ label: 'b', value: 2 }]); - }); - - test('当没有标签匹配时,返回原数组', () => { - const array = [ - { label: 'a', value: 1 }, - { label: 'b', value: 2 } - ]; - const keys = ['c', 'd']; - const result = yd_array_omitBy(array, keys); - expect(result).toEqual([ - { label: 'a', value: 1 }, - { label: 'b', value: 2 } - ]); - }); - - test('当所有标签匹配时,返回空数组', () => { - const array = [ - { label: 'a', value: 1 }, - { label: 'b', value: 2 } - ]; - const keys = ['a', 'b']; - const result = yd_array_omitBy(array, keys); - expect(result).toEqual([]); - }); - - test('处理空数组', () => { - const array = []; - const keys = ['a', 'b']; - const result = yd_array_omitBy(array, keys); - expect(result).toEqual([]); - }); - - test('处理空标签列表', () => { - const array = [ - { label: 'a', value: 1 }, - { label: 'b', value: 2 } - ]; - const keys = []; - const result = yd_array_omitBy(array, keys); - expect(result).toEqual([ - { label: 'a', value: 1 }, - { label: 'b', value: 2 } - ]); - }); -}); diff --git a/lib/array/paging.js b/lib/array/paging.js deleted file mode 100644 index 07ce6fd..0000000 --- a/lib/array/paging.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * 对数组进行分页 - * @author XiaoXinYo - * @category array - * @alias yd_array_paging - * @param {Array} array 需要分页的数组 - *@param {number} page_size 每页数量 - * @returns {Array} 返回已分页的数组 - * @example yd_array_paging([1, 2, 3, 4, 5, 6], 3); // [[1, 2, 3], [4, 5, 6]] - */ - -export default (array, page_size) => { - const result = []; - for (let i = 0; i < array.length; i += page_size) { - result.push(array.slice(i, i + page_size)); - } - return result; -}; diff --git a/lib/array/pick.js b/lib/array/pick.js deleted file mode 100644 index b791919..0000000 --- a/lib/array/pick.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * 从数组中选择指定标签的项 - * @alias yd_array_pick - * @category 数组操作 - * @param {Array} arrObj 数组对象 - * @param {string} field 匹配的字段 - * @param {Array} values 匹配的值 - * @returns {object[]} 返回一个新数组,其中只包含具有指定标签的项 - * @author 卞雪瑞 - * @author 陈随易 - * @summary 这个函数根据给定的标签列表,从数组中选择所有匹配这些标签的项,并返回这些项。 - * @example - * yd_array_pick( - * [{ label: 'a', value: 1 }, { label: 'b', value: 2 }, { label: 'c', value: 3 }], - * 'label', - * ['a', 'c'] - * ); - * 结果: - * [ - * { label: 'a', value: 1 }, - * { label: 'c', value: 3 } - * ] - */ -export default (arrObj, field, values = []) => { - return arrObj.filter((item) => values.includes(item[field])); -}; diff --git a/lib/array/pick.test.js b/lib/array/pick.test.js deleted file mode 100644 index 914b431..0000000 --- a/lib/array/pick.test.js +++ /dev/null @@ -1,54 +0,0 @@ -import { describe, expect, test } from 'vitest'; - -import yd_array_pick from './pick.js'; - -describe('yd_array_pick', () => { - test('根据标签选择数组中的项', () => { - const array = [ - { label: 'a', value: 1 }, - { label: 'b', value: 2 }, - { label: 'c', value: 3 } - ]; - const result = yd_array_pick(array, 'label', ['a', 'c']); - expect(result).toEqual([ - { label: 'a', value: 1 }, - { label: 'c', value: 3 } - ]); - }); - - test('当没有标签匹配时,返回空数组', () => { - const array = [ - { label: 'a', value: 1 }, - { label: 'b', value: 2 } - ]; - const result = yd_array_pick(array, 'label', ['c', 'd']); - expect(result).toEqual([]); - }); - - test('当所有标签都匹配时,返回原数组', () => { - const array = [ - { label: 'a', value: 1 }, - { label: 'b', value: 2 } - ]; - const result = yd_array_pick(array, 'label', ['a', 'b']); - expect(result).toEqual([ - { label: 'a', value: 1 }, - { label: 'b', value: 2 } - ]); - }); - - test('处理空数组', () => { - const array = []; - const result = yd_array_pick(array, 'label', ['a', 'b']); - expect(result).toEqual([]); - }); - - test('处理空标签列表', () => { - const array = [ - { label: 'a', value: 1 }, - { label: 'b', value: 2 } - ]; - const result = yd_array_pick(array, 'label', []); - expect(result).toEqual([]); - }); -}); diff --git a/lib/array/shuffle.js b/lib/array/shuffle.js deleted file mode 100644 index a664568..0000000 --- a/lib/array/shuffle.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * 数组随机排序(俗称洗牌) - * @author 生命过客 <739694218@qq.com> - * @category array - * @alias yd_array_shuffle - * @param {Array} array 数组 - * @returns {Array} 返回随机排序后的数组 - */ -export default (array = []) => { - return array.sort(() => Math.random() - 0.5); -}; diff --git a/lib/array/sort.js b/lib/array/sort.js deleted file mode 100644 index f27d5a5..0000000 --- a/lib/array/sort.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @description 排序 - * @author grantguo - * @category array - * @alias yd_array_sort - * @param { Array } array - * @param { Object } { order?: "asc" | "des", by?: it => it } - * @return 返回排序后的数组 - * @summary 根据传入的参数进行排序,返回排序后的数组 - * @example - * sort([1, 3, 2], { order: 'asc' }) - * // => [1, 2, 3] - * - * sort([1, 3, 2]) - * // => [1, 2, 3] - * - * sort([{a: 1, b: 2}, {a: 2, b: 4}], { order: 'des', by: item => item.b }) - * // => [{a: 2, b: 4}, {a: 1, b: 2}] - * - * sort([{a: 1, b: 2}, {a: 2, b: 4}], { order: 'des' }) - * // => [{a: 1, b: 2}, {a: 2, b: 4}] - * - */ - -export default (array, ...other) => { - other = other.length ? other : [{}]; - return [...array].sort((a, b) => { - for (const { order = 'asc', by = (item) => item } of other) { - const aValue = by(a); - const bValue = by(b); - if (aValue !== bValue) { - const compare = aValue > bValue ? 1 : -1; - return order === 'asc' ? compare : -compare; - } - } - }); -}; diff --git a/lib/array/sort.test.js b/lib/array/sort.test.js deleted file mode 100644 index 5a764fd..0000000 --- a/lib/array/sort.test.js +++ /dev/null @@ -1,20 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_array_sort from './sort.js'; - -describe('yd_array_sort', () => { - it('排序测试', () => { - const arr1 = yd_array_sort([1, 3, 2], { order: 'asc' }); - const arr2 = yd_array_sort( - [ - { a: 1, b: 2 }, - { a: 2, b: 4 } - ], - { order: 'des', by: (item) => item.b } - ); - expect(arr2).toEqual([ - { a: 2, b: 4 }, - { a: 1, b: 2 } - ]); - expect(arr1).toEqual([1, 2, 3]); - }); -}); diff --git a/lib/array/uniqWith.js b/lib/array/uniqWith.js deleted file mode 100644 index a4b684c..0000000 --- a/lib/array/uniqWith.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * 数组去重 - * @author 陈随易 - * @category array - * @alias yd_array_uniqWith - * @param {Array} array 数组数据 - * @param {Function} comparator 比较函数 - * @returns {Array} 返回比较函数去重后的数组 - */ -export default (array, comparator) => { - const uniqueSet = new Set(); - const result = []; - - for (const item of array) { - let isDuplicate = false; - for (const existingItem of uniqueSet) { - if (comparator(item, existingItem)) { - isDuplicate = true; - break; - } - } - if (!isDuplicate) { - uniqueSet.add(item); - result.push(item); - } - } - - return result; -}; diff --git a/lib/array/unique.js b/lib/array/unique.js deleted file mode 100644 index f42f82e..0000000 --- a/lib/array/unique.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * 数组去重 - * @alias yd_array_unique - * @category array - * @param {Array} array 数组数据 - * @returns {Array} 返回去重后的数组 - * @author 陈随易 - * @example yd_array_unique([1,1,2,2,3,3]) // [1,2,3] - */ -export default (array) => { - return [...new Set(array)]; -}; diff --git a/lib/array/uniqueByField.js b/lib/array/uniqueByField.js deleted file mode 100644 index 18fb545..0000000 --- a/lib/array/uniqueByField.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * 对象数组根据某个字段去重 - * @author 生命过客 <739694218@qq.com> - * @category array - * @alias yd_array_uniqueByField - * @param {Array} arr 对象数组 - * @returns {string} field 要去重的字段 - * @summary 根据 field 对数组 arr 进行去重 - * @example - * yd_array_uniqueByField([{age:20,name:'Andy'}, {age: 21,name:'Jack'}, {age:20,name:'Jenson'}], 'age'); - * 结果:[{age:20,name:'Andy'}, {age: 21,name:'Jack'}] - */ -export default (arr, field) => { - const map = new Map(); // 利用 Map 特性, 可以做到高性能 - return arr.filter((item) => !map.has(item[field]) && map.set(item[field], 1)); -}; diff --git a/lib/array/uniqueByField.test.js b/lib/array/uniqueByField.test.js deleted file mode 100644 index 4bf290b..0000000 --- a/lib/array/uniqueByField.test.js +++ /dev/null @@ -1,34 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_array_uniqueByField from './uniqueByField.js'; - -describe('yd_array_uniqueByField', () => { - it('returns unique array by age', () => { - const array = [ - { age: 20, name: 'Andy' }, - { age: 21, name: 'Jack' }, - { age: 20, name: 'Jenson' } - ]; - const result = yd_array_uniqueByField(array, 'age'); - expect(result).toEqual([ - { age: 20, name: 'Andy' }, - { age: 21, name: 'Jack' } - ]); - }); - - it('returns unique array by class', () => { - const array = [ - { age: 20, name: 'Andy', class: 'English' }, - { age: 21, name: 'Jack', class: 'History' }, - { age: 20, name: 'Jenson', class: 'Physics' }, - { age: 22, name: 'Cherry', class: 'Computer' }, - { age: 20, name: 'Polly', class: 'English' } - ]; - const result = yd_array_uniqueByField(array, 'class'); - expect(result).toEqual([ - { age: 20, name: 'Andy', class: 'English' }, - { age: 21, name: 'Jack', class: 'History' }, - { age: 20, name: 'Jenson', class: 'Physics' }, - { age: 22, name: 'Cherry', class: 'Computer' } - ]); - }); -}); diff --git a/lib/browser/isMobileDevice.js b/lib/browser/isMobileDevice.js index 836c2bd..6d84fda 100644 --- a/lib/browser/isMobileDevice.js +++ b/lib/browser/isMobileDevice.js @@ -1,9 +1,9 @@ /** * 判断是不是当前用户的是不是移动设备 - * @author 挺可怜的一人 https://github.com/mhpsy - * @category browser * @alias yd_browser_isMobileDevices + * @category browser * @returns {boolean} 返回是否是移动设备 + * @author 挺可怜的一人 https://github.com/mhpsy * @example yd_browser_isMobileDevices() => true */ export default () => { diff --git a/lib/crypto/luhn.js b/lib/crypto/luhn.js index 0b8b30c..808724d 100644 --- a/lib/crypto/luhn.js +++ b/lib/crypto/luhn.js @@ -1,11 +1,11 @@ /** * 信用卡验证算法 - * @alias yd_ctypto_luhn - * @category ctypto + * @alias yd_crypto_luhn + * @category crypto * @param {string} str 信用卡卡号 * @returns {number} 信用卡验证树枝 * @author 陈随易 - * @example yd_ctypto_luhn('1234456789') // 1 + * @example yd_crypto_luhn('1234456789') // 1 */ export default (str) => { const ord = 48; diff --git a/lib/crypto/md5.js b/lib/crypto/md5.js deleted file mode 100644 index 7aac7c8..0000000 --- a/lib/crypto/md5.js +++ /dev/null @@ -1,268 +0,0 @@ -/* - * JavaScript MD5 - * https://github.com/blueimp/JavaScript-MD5 - * - * Copyright 2011, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - * - * Based on - * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message - * Digest Algorithm, as defined in RFC 1321. - * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * Distributed under the BSD License - * See http://pajhome.org.uk/crypt/md5 for more info. - */ - -// Add integers, wrapping at 2^32. -// This uses 16-bit operations internally to work around bugs in interpreters. -function safeAdd(x, y) { - let lsw = (x & 0xffff) + (y & 0xffff); - let msw = (x >> 16) + (y >> 16) + (lsw >> 16); - return (msw << 16) | (lsw & 0xffff); -} - -// Bitwise rotate a 32-bit number to the left. -function bitRotateLeft(num, cnt) { - return (num << cnt) | (num >>> (32 - cnt)); -} - -// Basic operation the algorithm uses. -function md5cmn(q, a, b, x, s, t) { - return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b); -} - -// Basic operation the algorithm uses. -function md5ff(a, b, c, d, x, s, t) { - return md5cmn((b & c) | (~b & d), a, b, x, s, t); -} - -// Basic operation the algorithm uses. -function md5gg(a, b, c, d, x, s, t) { - return md5cmn((b & d) | (c & ~d), a, b, x, s, t); -} - -// Basic operation the algorithm uses. -function md5hh(a, b, c, d, x, s, t) { - return md5cmn(b ^ c ^ d, a, b, x, s, t); -} - -// Basic operation the algorithm uses. -function md5ii(a, b, c, d, x, s, t) { - return md5cmn(c ^ (b | ~d), a, b, x, s, t); -} - -// Calculate the MD5 of an array of little-endian words, and a bit length. -function binlMD5(x, len) { - /* append padding */ - x[len >> 5] |= 0x80 << len % 32; - x[(((len + 64) >>> 9) << 4) + 14] = len; - - let i; - let olda; - let oldb; - let oldc; - let oldd; - let a = 1732584193; - let b = -271733879; - let c = -1732584194; - let d = 271733878; - - for (i = 0; i < x.length; i += 16) { - olda = a; - oldb = b; - oldc = c; - oldd = d; - - a = md5ff(a, b, c, d, x[i], 7, -680876936); - d = md5ff(d, a, b, c, x[i + 1], 12, -389564586); - c = md5ff(c, d, a, b, x[i + 2], 17, 606105819); - b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330); - a = md5ff(a, b, c, d, x[i + 4], 7, -176418897); - d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426); - c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341); - b = md5ff(b, c, d, a, x[i + 7], 22, -45705983); - a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416); - d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417); - c = md5ff(c, d, a, b, x[i + 10], 17, -42063); - b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162); - a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682); - d = md5ff(d, a, b, c, x[i + 13], 12, -40341101); - c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290); - b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329); - - a = md5gg(a, b, c, d, x[i + 1], 5, -165796510); - d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632); - c = md5gg(c, d, a, b, x[i + 11], 14, 643717713); - b = md5gg(b, c, d, a, x[i], 20, -373897302); - a = md5gg(a, b, c, d, x[i + 5], 5, -701558691); - d = md5gg(d, a, b, c, x[i + 10], 9, 38016083); - c = md5gg(c, d, a, b, x[i + 15], 14, -660478335); - b = md5gg(b, c, d, a, x[i + 4], 20, -405537848); - a = md5gg(a, b, c, d, x[i + 9], 5, 568446438); - d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690); - c = md5gg(c, d, a, b, x[i + 3], 14, -187363961); - b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501); - a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467); - d = md5gg(d, a, b, c, x[i + 2], 9, -51403784); - c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473); - b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734); - - a = md5hh(a, b, c, d, x[i + 5], 4, -378558); - d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463); - c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562); - b = md5hh(b, c, d, a, x[i + 14], 23, -35309556); - a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060); - d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353); - c = md5hh(c, d, a, b, x[i + 7], 16, -155497632); - b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640); - a = md5hh(a, b, c, d, x[i + 13], 4, 681279174); - d = md5hh(d, a, b, c, x[i], 11, -358537222); - c = md5hh(c, d, a, b, x[i + 3], 16, -722521979); - b = md5hh(b, c, d, a, x[i + 6], 23, 76029189); - a = md5hh(a, b, c, d, x[i + 9], 4, -640364487); - d = md5hh(d, a, b, c, x[i + 12], 11, -421815835); - c = md5hh(c, d, a, b, x[i + 15], 16, 530742520); - b = md5hh(b, c, d, a, x[i + 2], 23, -995338651); - - a = md5ii(a, b, c, d, x[i], 6, -198630844); - d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415); - c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905); - b = md5ii(b, c, d, a, x[i + 5], 21, -57434055); - a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571); - d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606); - c = md5ii(c, d, a, b, x[i + 10], 15, -1051523); - b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799); - a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359); - d = md5ii(d, a, b, c, x[i + 15], 10, -30611744); - c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380); - b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649); - a = md5ii(a, b, c, d, x[i + 4], 6, -145523070); - d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379); - c = md5ii(c, d, a, b, x[i + 2], 15, 718787259); - b = md5ii(b, c, d, a, x[i + 9], 21, -343485551); - - a = safeAdd(a, olda); - b = safeAdd(b, oldb); - c = safeAdd(c, oldc); - d = safeAdd(d, oldd); - } - return [a, b, c, d]; -} - -// Convert an array of little-endian words to a string -function binl2rstr(input) { - let i; - let output = ''; - let length32 = input.length * 32; - for (i = 0; i < length32; i += 8) { - output += String.fromCharCode((input[i >> 5] >>> i % 32) & 0xff); - } - return output; -} - -// Convert a raw string to an array of little-endian words -// Characters >255 have their high-byte silently ignored. -function rstr2binl(input) { - let i; - let output = []; - output[(input.length >> 2) - 1] = undefined; - for (i = 0; i < output.length; i += 1) { - output[i] = 0; - } - let length8 = input.length * 8; - for (i = 0; i < length8; i += 8) { - output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << i % 32; - } - return output; -} - -// Calculate the MD5 of a raw string -function rstrMD5(s) { - return binl2rstr(binlMD5(rstr2binl(s), s.length * 8)); -} - -// Calculates the HMAC-MD5 of a key and some data (raw strings) -function rstrHMACMD5(key, data) { - let i; - let bkey = rstr2binl(key); - let ipad = []; - let opad = []; - let hash; - ipad[15] = opad[15] = undefined; - if (bkey.length > 16) { - bkey = binlMD5(bkey, key.length * 8); - } - for (i = 0; i < 16; i += 1) { - ipad[i] = bkey[i] ^ 0x36363636; - opad[i] = bkey[i] ^ 0x5c5c5c5c; - } - hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8); - return binl2rstr(binlMD5(opad.concat(hash), 512 + 128)); -} - -// Convert a raw string to a hex string -function rstr2hex(input) { - let hexTab = '0123456789abcdef'; - let output = ''; - let x; - let i; - for (i = 0; i < input.length; i += 1) { - x = input.charCodeAt(i); - output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f); - } - return output; -} - -// Encode a string as UTF-8 -function str2rstrUTF8(input) { - return unescape(encodeURIComponent(input)); -} - -// Encodes input string as raw MD5 string - -function rawMD5(s) { - return rstrMD5(str2rstrUTF8(s)); -} - -// Encodes input string as Hex encoded string -function hexMD5(s) { - return rstr2hex(rawMD5(s)); -} - -// Calculates the raw HMAC-MD5 for the given key and data -function rawHMACMD5(k, d) { - return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d)); -} - -// Calculates the Hex encoded HMAC-MD5 for the given key and data -function hexHMACMD5(k, d) { - return rstr2hex(rawHMACMD5(k, d)); -} - -/** - * 计算MD5值 - * @alias yd_ctypto_md5 - * @category crypto - * @param {string} string 输入字符串 - * @param {string} [key] HMAC key - * @param {boolean} [raw] Raw output switch - * @returns {string} 返回MD5值 - * @author https://github.com/blueimp/JavaScript-MD5 - * @example - */ -export default (string, key, raw) => { - if (!key) { - if (!raw) { - return hexMD5(string); - } - return rawMD5(string); - } - if (!raw) { - return hexHMACMD5(key, string); - } - return rawHMACMD5(key, string); -}; diff --git a/lib/datetime/computeAge.js b/lib/datetime/computeAge.js index 887d22b..8a66bf2 100644 --- a/lib/datetime/computeAge.js +++ b/lib/datetime/computeAge.js @@ -2,15 +2,15 @@ import { parseISO, isValid, differenceInYears, isBefore } from 'date-fns'; /** * 计算年龄 - * - * @author 卞雪瑞 - * @category 时间操作 * @alias yd_compute_age - * @param {String} birthday - 生日日期字符串 + * @category datetime + * @param {string} birthday - 生日日期字符串 + * @returns {number} - 返回计算出的年龄,如果未提供生日则返回0 + * @author 卞雪瑞 * @summary 根据给的生日计算出用户的年龄 - * @returns {Number} - 返回计算出的年龄,如果未提供生日则返回0 + * @example yd_compute_age() */ -const computeAge = (birthday) => { +export default (birthday) => { if (birthday) { const _birthday = parseISO(birthday); @@ -29,5 +29,3 @@ const computeAge = (birthday) => { } return 0; }; - -export default computeAge; diff --git a/lib/datetime/customFormat.js b/lib/datetime/customFormat.js deleted file mode 100644 index b56079f..0000000 --- a/lib/datetime/customFormat.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * 获取格式化的当前日期和时间,支持自定义格式。 - * @author penn - * @category datetime - * @alias yd_datetime_customFormat - * @param {string} [format="YYYY-MM-DD_HH-mm-SS"] - 可选的日期时间格式。 - * @returns {string} 格式化后的日期时间字符串。 - * - * @example - * console.log(yd_datetime_customFormat()) // 输出: "2024-07-30_15-45-30" - * - * @example - * console.log(yd_datetime_customFormat("DD/MM/YYYY HH:mm:SS")) // 输出: "30/07/2024 15:45:30" - * - * @example - * console.log(yd_datetime_customFormat("MM-DD-YYYY")) // 输出: "07-30-2024" - */ -export default (format = 'YYYY-MM-DD_HH-mm-SS') => { - try { - if (typeof format !== 'string' || !format.match(/(YYYY|MM|DD|HH|mm|SS)/)) { - throw new Error('日期格式无效'); - } - const now = new Date(); - const year = now.getFullYear(); - const month = (now.getMonth() + 1).toString().padStart(2, '0'); - const day = now.getDate().toString().padStart(2, '0'); - const hours = now.getHours().toString().padStart(2, '0'); - const minutes = now.getMinutes().toString().padStart(2, '0'); - const seconds = now.getSeconds().toString().padStart(2, '0'); - - // 使用相应的值替换格式中的占位符 - const formattedDateTime = format - // - .replace('YYYY', year) - .replace('MM', month) - .replace('mm', minutes) - .replace('DD', day) - .replace('HH', hours) - .replace('SS', seconds); - - return formattedDateTime; - } catch (error) { - console.error('格式化日期时出错:', error); - return null; - } -}; diff --git a/lib/datetime/customFormat.test.js b/lib/datetime/customFormat.test.js deleted file mode 100644 index 07dfe3f..0000000 --- a/lib/datetime/customFormat.test.js +++ /dev/null @@ -1,33 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_datetime_customFormat from './customFormat.js'; - -describe('yd_datetime_customFormat', () => { - it('should return the current date and time in default format "YYYY-MM-DD_HH-mm-SS"', () => { - const result = yd_datetime_customFormat(); - const regex = /^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}$/; - expect(result).toMatch(regex); - }); - - it('should format the current date and time as "DD/MM/YYYY HH:mm:SS"', () => { - const result = yd_datetime_customFormat('DD/MM/YYYY HH:mm:SS'); - const regex = /^\d{2}\/\d{2}\/\d{4} \d{2}:\d{2}:\d{2}$/; - expect(result).toMatch(regex); - }); - - it('should format the current date and time as "MM-DD-YYYY"', () => { - const result = yd_datetime_customFormat('MM-DD-YYYY'); - const regex = /^\d{2}-\d{2}-\d{4}$/; - expect(result).toMatch(regex); - }); - - it('should handle custom format "YYYY MM DD HH mm SS"', () => { - const result = yd_datetime_customFormat('YYYY MM DD HH mm SS'); - const regex = /^\d{4} \d{2} \d{2} \d{2} \d{2} \d{2}$/; - expect(result).toMatch(regex); - }); - - it('should return null and log an error if an invalid date format is used', () => { - const result = yd_datetime_customFormat('INVALID-FORMAT'); - expect(result).toBeNull(); - }); -}); diff --git a/lib/datetime/dateRange.js b/lib/datetime/dateRange.js index 8913ed4..43b1bdc 100644 --- a/lib/datetime/dateRange.js +++ b/lib/datetime/dateRange.js @@ -3,7 +3,7 @@ import { add, isBefore } from 'date-fns'; /** * 返回一个时间范围 * @alias yd_date_range - * @category 时间操作 + * @category datetime * @param {number} year - 需要增加的年数,默认为0 * @param {number} month - 需要增加的月数,默认为0 * @param {number} day - 需要增加的天数,默认为0 diff --git a/lib/datetime/format.js b/lib/datetime/format.js deleted file mode 100644 index 66d0cc0..0000000 --- a/lib/datetime/format.js +++ /dev/null @@ -1,10 +0,0 @@ -import { format } from 'date-fns'; - -/** - * 格式化时间 - * @alias yd_datetime_format - * @category datetime - * @returns {string} 格式化后的时间 - * @author https://github.com/date-fns/date-fns - */ -export default format; diff --git a/lib/datetime/getDays.js b/lib/datetime/getDays.js deleted file mode 100644 index 3fa2f41..0000000 --- a/lib/datetime/getDays.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @description 返回某年某月天数 - * @author grantguo - * @category datetime - * @alias yd_dateTime_getDays - * @param { number } year 年 - * @param { number } month 月 - * @return 返回某年某月天数 - * @summary 返回某年某月天数 - * @example - * - * const days_1 = yd_dateTime_getDays() - * // => 31 - * const days_2 = yd_dateTime_getDays(2024,9) - * // => 30 - */ - -export default (year = getYear(), month = getNumMonth()) => { - const date = new Date(year, month, 0); - return date.getDate(); -}; - -const date = new Date(); -/* 获取年份 */ -const getYear = () => { - return date.getFullYear(); -}; - -/* 获取月份 */ -const getMonth = () => { - return (date.getMonth() + 1).toString().padStart(2, '0'); -}; - -const getNumMonth = () => { - return date.getMonth() + 1; -}; diff --git a/lib/datetime/getDays.test.js b/lib/datetime/getDays.test.js deleted file mode 100644 index b238be9..0000000 --- a/lib/datetime/getDays.test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_dateTime_getDays from './getDays.js'; - -describe('yd_dateTime_getDays', () => { - it('shoule get a number days', () => { - const days_1 = yd_dateTime_getDays(); - expect(days_1).toEqual(31); - const days_2 = yd_dateTime_getDays(2024, 9); - expect(days_2).toEqual(30); - }); -}); diff --git a/lib/datetime/stringToDate.js b/lib/datetime/stringToDate.js deleted file mode 100644 index 1cae14c..0000000 --- a/lib/datetime/stringToDate.js +++ /dev/null @@ -1,80 +0,0 @@ -/** - * 将日期时间字符串根据指定格式转换为 Date 对象,并可选时区。 - * 支持多种字符串格式,并验证输入格式的正确性。 - * @author penn - * @category datetime - * @alias yd_datetime_stringToDate - * @param {string} timeStr - 日期时间字符串(例如:"2021-01-01 00:00:00")。 - * @param {string} format - 日期时间字符串的格式(例如:"YYYY-MM-DD HH:mm:SS")。 - * @param {number} [timezoneOffset=0] - 可选的时区偏移量,以小时为单位,相对于UTC时间。 - * @returns {Date|null} 转换后对应的 Date 对象,如果格式不匹配则返回 null。 - * - * @example - * // 示例: 格式 "YYYY-MM-DD HH:mm:SS",UTC-5 - * const date1 = stringToDate"2021-01-01 00:00:00", "YYYY-MM-DD HH:mm:SS", -5 - * console.log(date1) // 输出: Date 对象,调整至时区: UTC-5 - * - * @example - * // 示例: 格式 "YYYY-MM-DD_HH-mm-SS" - * const date2 = stringToDate("2021-01-01_00-00-00", "YYYY-MM-DD_HH-mm-SS") - * console.log(date2) // 输出: Date 对象 - * - * @example - * // 示例: 格式 "DD/MM/YYYY HH:mm:SS" - * const date3 = stringToDate("01/01/2021 00:00:00", "DD/MM/YYYY HH:mm:SS") - * console.log(date3) // 输出: Date 对象 - * - * @example - * // 示例: 格式 "MM-DD-YYYY" - * const date4 = stringToDate("01-01-2021", "MM-DD-YYYY") - * console.log(date4) // 输出: Date 对象 - */ - -export default (timeStr, format, timezoneOffset = 0) => { - const formatMapping = { - YYYY: 0, - MM: 1, - DD: 2, - HH: 3, - mm: 4, - SS: 5 - }; - - const regexMapping = { - 'YYYY-MM-DD HH:mm:SS': /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/, - 'YYYY-MM-DD_HH-mm-SS': /(\d{4})-(\d{2})-(\d{2})_(\d{2})-(\d{2})-(\d{2})/, - 'DD/MM/YYYY HH:mm:SS': /(\d{2})\/(\d{2})\/(\d{4}) (\d{2}):(\d{2}):(\d{2})/, - 'MM-DD-YYYY': /(\d{2})-(\d{2})-(\d{4})/ - }; - - // 检查 format 格式 - if (!regexMapping[format]) { - console.error('不支持的日期格式。'); - return null; - } - - // 使用相应的正则表达式验证并提取 - const match = timeStr.match(regexMapping[format]); - if (!match) { - console.error('日期字符串格式无效。'); - return null; - } - - let dateParts = [1970, 0, 1, 0, 0, 0]; // 默认日期: [年, 月, 日, 时, 分, 秒] - - const partsOrder = format.match(/(YYYY|MM|DD|HH|mm|SS)/g); - - partsOrder.forEach((part, index) => { - if (formatMapping[part] !== undefined) { - let value = parseInt(match[index + 1], 10); - if (part === 'MM') value -= 1; // JavaScript的月份索引从 0 开始 - dateParts[formatMapping[part]] = value; - } - }); - - // 时区处理 - const dateUTC = new Date(Date.UTC(...dateParts)); - const dateWithOffset = new Date(dateUTC.getTime() + timezoneOffset * 3600 * 1000); - - return dateWithOffset; -}; diff --git a/lib/datetime/stringToDate.test.js b/lib/datetime/stringToDate.test.js deleted file mode 100644 index 3c17ed1..0000000 --- a/lib/datetime/stringToDate.test.js +++ /dev/null @@ -1,52 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_datetime_stringToDate from './stringToDate'; - -describe('yd_datetime_stringToDate', () => { - it("should return a corresponding Date object for the 'YYYY-MM-DD HH:mm:SS' format"), - () => { - const date = yd_datetime_stringToDate('2024-01-01 00:00:00', 'YYYY-MM-DD HH:mm:SS'); - expect(date).toEqual(new Date(Date.UTC(2024, 0, 1, 0, 0, 0))); - }; - - it("should return a corresponding Date object for the 'YYYY-MM-DD_HH:mm:SS' format"), - () => { - const date = yd_datetime_stringToDate('2024-01-01_00:00:00', 'YYYY-MM-DD_HH:mm:SS'); - expect(date).toEqual(new Date(Date.UTC(2024, 0, 1, 0, 0, 0))); - }; - - it("should return a corresponding Date object for the 'DD/MM/YYYY HH:mm:SS' format"), - () => { - const date = yd_datetime_stringToDate('01/01/2024 00:00:00', 'DD/MM/YYYY HH:mm:SS'); - expect(date).toEqual(new Date(Date.UTC(2024, 0, 1, 0, 0, 0))); - }; - - it("should return a corresponding Date object for the 'MM-DD-YYYY' format"), - () => { - const date = yd_datetime_stringToDate('01-01-2024', 'MM-DD-YYYY'); - expect(date).toEqual(new Date(Date.UTC(2024, 0, 1, 0, 0, 0))); - }; - - it('should return null for an invalid format'), - () => { - const format = 'mm-dd-yy'; - const result = yd_datetime_stringToDate('01-01-2024', format); - expect(result).toBeNull(); - }; - - it('should return null for a invalid date string'), - () => { - const date = yd_datetime_stringToDate('invalid', 'YYYY-MM-DD HH:mm:SS'); - expect(date).toBeNull(); - }; - - it('should correctly adjust for timezone offset'), - () => { - const date = yd_datetime_stringToDate('2024-01-01 00:00:00', 'YYYY-MM-DD HH:mm:SS', -5); // UTC-5 - expect(date).toEqual(new Date(Date.UTC(2024, 0, 1, 5, 0, 0))); - }; - - it('should correctly convert to UTC string', () => { - const date = yd_datetime_stringToDate('2024-01-01 00:00:00', 'YYYY-MM-DD HH:mm:SS', -5); // UTC-5 - expect(date.toUTCString()).toBe('Sun, 31 Dec 2023 19:00:00 GMT'); - }); -}); diff --git a/lib/datetime/timestampToDate.js b/lib/datetime/timestampToDate.js deleted file mode 100644 index 6979149..0000000 --- a/lib/datetime/timestampToDate.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * 将 Unix 时间戳转换为 Date 对象。 - * 支持秒级 (10位数字) 和毫秒级 (13位数字) 的 Unix 时间戳。 - * 验证时间戳是否有效,并自动调整精度。 - * @author penn - * @category datetime - * @alias yd_datetime_timestampToDate - * @param {number|string} ts - Unix 时间戳。 - * @returns {Date|null} 对应的 Date 对象,如果时间戳无效或格式不正确则返回 null。 - * - * @example - * // 示例: 有效的秒级时间戳 - * console.log(timestampToDate(1704067200)); // 输出: Date 对象,代表 2024-01-01 00:00:00 UTC - * - * @example - * // 示例: 有效的毫秒级时间戳 - * console.log(timestampToDate(1704067200000)); // 输出: Date 对象,代表 2024-01-01 00:00:00 UTC - * - * @example - * // 示例: 无效的时间戳 - * console.log(timestampToDate("invalid")); // 输出: null - */ -export default (ts) => { - if (typeof ts === 'string') { - ts = parseInt(ts, 10); - } - - if (typeof ts !== 'number' || isNaN(ts) || ts < 0) { - console.error('Invalid timestamp.'); - return null; - } - - if (ts.toString().length === 10) { - return new Date(ts * 1000); - } else if (ts.toString().length === 13) { - return new Date(ts); - } else { - console.error('Timestamp must be either 10 or 13 digits long.'); - return null; - } -}; diff --git a/lib/datetime/timestampToDate.test.js b/lib/datetime/timestampToDate.test.js deleted file mode 100644 index bfa0b57..0000000 --- a/lib/datetime/timestampToDate.test.js +++ /dev/null @@ -1,48 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_datetime_timestampToDate from './timestampToDate.js'; - -describe('yd_datetime_timestampToDate', () => { - it('should return a Date object for valid 10-digit second-level timestamp', () => { - const ts = 1704067200; - const expectedDate = new Date(ts * 1000); - expect(yd_datetime_timestampToDate(ts)).toEqual(expectedDate); - }); - - it('should return a Date object for valid 13-digit millisecond-level timestamp', () => { - const ts = 1704067200000; - const expectedDate = new Date(ts); - expect(yd_datetime_timestampToDate(ts)).toEqual(expectedDate); - }); - - it('should handle string input and return a Date object for valid 10-digit second-level timestamp', () => { - const ts = '1704067200'; - const expectedDate = new Date(parseInt(ts, 10) * 1000); - expect(yd_datetime_timestampToDate(ts)).toEqual(expectedDate); - }); - - it('should handle string input and return a Date object for valid 13-digit millisecond-level timestamp', () => { - const ts = '1704067200000'; - const expectedDate = new Date(parseInt(ts, 10)); - expect(yd_datetime_timestampToDate(ts)).toEqual(expectedDate); - }); - - it('should return null for invalid timestamp string', () => { - expect(yd_datetime_timestampToDate('invalid')).toBeNull(); - }); - - it('should return null for non-numeric input', () => { - expect(yd_datetime_timestampToDate(null)).toBeNull(); - expect(yd_datetime_timestampToDate(undefined)).toBeNull(); - expect(yd_datetime_timestampToDate({})).toBeNull(); - expect(yd_datetime_timestampToDate([])).toBeNull(); - }); - - it('should return null for negative numbers', () => { - expect(yd_datetime_timestampToDate(-1234567890)).toBeNull(); - }); - - it('should return null for timestamps that are neither 10 nor 13 digits long', () => { - expect(yd_datetime_timestampToDate(123)).toBeNull(); - expect(yd_datetime_timestampToDate(123456789012)).toBeNull(); - }); -}); diff --git a/lib/datetime/week.js b/lib/datetime/week.js deleted file mode 100644 index 0ee1fc4..0000000 --- a/lib/datetime/week.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * 返回当前日期是星期几 - * @author tank - * @category datetime - * @alias yd_datetime_week - * @returns {string} 周几 - */ -export default () => { - const date = new Date(); - const day = date.getDay(); - const names = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; - return names[day]; -}; diff --git a/lib/file/dataURLtoFile.js b/lib/file/dataURLtoFile.js index 4166df2..6575169 100644 --- a/lib/file/dataURLtoFile.js +++ b/lib/file/dataURLtoFile.js @@ -1,21 +1,22 @@ /** * Base64 DataURL 转 文件 - * @author wzskyline - * @category file * @alias yd_file_dataURLtoFile - * @param {Object} dataurl Base64 DataURL - * @param {Function} callback 回调函数 + * @category file + * @param filename + * @param {object} dataurl Base64 DataURL + * @param {Function} callback 回调函数 + * @returns {File} 返回文件对象 + * @author wzskyline * @example yd_file_dataURLtoFile('base64.....') -> File */ -export default (dataurl, filename="filename") => { - let arr = dataurl.split(","), - mime = arr[0].match(/:(.*?);/)[1], - bstr = atob(arr[1]), - n = bstr.length, - u8arr = new Uint8Array(n); - while (n--) { - u8arr[n] = bstr.charCodeAt(n); - } - return new File([u8arr], filename, { type: mime }); +export default (dataurl, filename = 'filename') => { + let arr = dataurl.split(','), + mime = arr[0].match(/:(.*?);/)[1], + bstr = atob(arr[1]), + n = bstr.length, + u8arr = new Uint8Array(n); + while (n--) { + u8arr[n] = bstr.charCodeAt(n); + } + return new File([u8arr], filename, { type: mime }); }; - \ No newline at end of file diff --git a/lib/file/fileInfo.js b/lib/file/fileInfo.js index 07b73b6..18aca79 100644 --- a/lib/file/fileInfo.js +++ b/lib/file/fileInfo.js @@ -1,16 +1,16 @@ /** * 从路径中截取文件信息 - * @author wzskyline - * @category file * @alias yd_file_fileInfo - * @param {String} path 路径参数 - * @returns {Object} 文件的信息 + * @category file + * @param {string} path 路径参数 + * @returns {object} 文件的信息 + * @author wzskyline * @example yd_file_fileInfo('/path/to/file.png') -> {name: 'file', type: 'png', fullName: 'file.png'} */ export default (path) => { - return { - name: path.replace(/(.*\/)*([^.]+).*/gi, "$2"), - type: path.replace(/.+\./, "").toLowerCase(), - fullName: path.split("/").pop() - }; + return { + name: path.replace(/(.*\/)*([^.]+).*/g, '$2'), + type: path.replace(/.+\./, '').toLowerCase(), + fullName: path.split('/').pop() + }; }; diff --git a/lib/file/fileToDataURL.js b/lib/file/fileToDataURL.js index a1d8380..f160d68 100644 --- a/lib/file/fileToDataURL.js +++ b/lib/file/fileToDataURL.js @@ -1,17 +1,16 @@ /** * 文件转Base64 DataURL - * @author wzskyline - * @category file * @alias yd_file_fileToDataURL - * @param {Object} object 文件或者blob对象 - * @param {Function} callback 回调函数 - * @example yd_file_fileToDataURL(file,()=>{}) + * @category file + * @param {object} object 文件或者blob对象 + * @param {Function} callback 回调函数 + * @author wzskyline + * @example yd_file_fileToDataURL(file,()=>{}) */ -export default (object,callback) => { +export default (object, callback) => { const freader = new FileReader(); freader.readAsDataURL(object); - freader.onload = function(e) { + freader.onload = function (e) { callback(e.target.result); }; }; - \ No newline at end of file diff --git a/lib/file/formatFileSize.js b/lib/file/formatFileSize.js deleted file mode 100644 index 0a39398..0000000 --- a/lib/file/formatFileSize.js +++ /dev/null @@ -1,32 +0,0 @@ -import isNumber from '../is/number.js'; - -const parseNum = (num) => { - return parseFloat(num.toFixed(2)); -}; - -/** - * 格式化文件大小 - * @alias yd_file_formatFileSize - * @category file - * @param {number} fileSize 文件大小,以字节为单位 - * @returns {string} 格式化后的文件大小,包含单位 - * @author 黄方明 - * @example yd_file_formatFileSize(500) => "500 Bytes" - * @example yd_file_formatFileSize(2048) => "2 KB" - * @example yd_file_formatFileSize(1048576) => "1 MB" - * @example yd_file_formatFileSize(1073741824) => "1 GB" - */ -export default (fileSize) => { - if (!isNumber(fileSize)) { - throw new Error('fileSize must be a number'); - } - if (fileSize < 1024) { - return parseNum(fileSize) + ' Bytes'; - } else if (fileSize < 1024 * 1024) { - return parseNum(fileSize / 1024) + ' KB'; - } else if (fileSize < 1024 * 1024 * 1024) { - return parseNum(fileSize / (1024 * 1024)) + ' MB'; - } else { - return parseNum(fileSize / (1024 * 1024 * 1024)) + ' GB'; - } -}; diff --git a/lib/file/formatFileSize.test.js b/lib/file/formatFileSize.test.js deleted file mode 100644 index 805044a..0000000 --- a/lib/file/formatFileSize.test.js +++ /dev/null @@ -1,33 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import yd_file_formatFileSize from './formatFileSize.js'; - -describe('yd_file_formatFileSize', () => { - it('should return correct size in Bytes', () => { - expect(yd_file_formatFileSize(500)).toBe('500 Bytes'); - expect(yd_file_formatFileSize(1023)).toBe('1023 Bytes'); - }); - - it('should return correct size in KB', () => { - expect(yd_file_formatFileSize(1024)).toBe('1 KB'); - expect(yd_file_formatFileSize(2048)).toBe('2 KB'); - expect(yd_file_formatFileSize(10240)).toBe('10 KB'); - }); - - it('should return correct size in MB', () => { - expect(yd_file_formatFileSize(1048576)).toBe('1 MB'); - expect(yd_file_formatFileSize(2097152)).toBe('2 MB'); - expect(yd_file_formatFileSize(10485760)).toBe('10 MB'); - }); - - it('should return correct size in GB', () => { - expect(yd_file_formatFileSize(1073741824)).toBe('1 GB'); - expect(yd_file_formatFileSize(2147483648)).toBe('2 GB'); - expect(yd_file_formatFileSize(10737418240)).toBe('10 GB'); - }); - - it('should throw an error for invalid input', () => { - expect(() => yd_file_formatFileSize('not a number')).toThrowError('fileSize must be a number'); - expect(() => yd_file_formatFileSize(true)).toThrowError('fileSize must be a number'); - expect(() => yd_file_formatFileSize(null)).toThrowError('fileSize must be a number'); - }); -}); diff --git a/lib/function/curry.js b/lib/function/curry.js deleted file mode 100644 index e557e65..0000000 --- a/lib/function/curry.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * 函数柯里化 - * @author fengxie <1015806955@qq.com> - * @category function - * @alias yd_function_curry - * @param func - * @returns {any} 返回传入函数中的返回值 - * @summary 将普通函数转换为柯里化形式 - * @example - * function sum(a, b, c) { - * return a + b + c - * } - * - * let curriedSum = curry(sum) - * console.log(curriedSum(1, 2, 3)) // 原函数任然可以被正常调用 - * console.log(curriedSum(1)(2, 3)) // 对第一个参数的柯里化 - * console.log(curriedSum(1)(2)(3)) // 对所有参数柯里化 - * 结果: - * 6 - * 6 - * 6 - */ -const curry = (func) => { - return function curried(...args) { - if (args.length >= func.length) { - return func.apply(this, args); - } else { - return function (...args2) { - return curried.apply(this, args.concat(args2)); - }; - } - }; -}; -export default curry; diff --git a/lib/function/curry.test.js b/lib/function/curry.test.js deleted file mode 100644 index dfcfcc3..0000000 --- a/lib/function/curry.test.js +++ /dev/null @@ -1,32 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_function_curry from './curry.js'; - -describe('yd_function_curry', () => { - const sum = (a, b, c) => a + b + c; - it('should return the sum when all arguments are provided at once', () => { - const curriedSum = yd_function_curry(sum); - expect(curriedSum(1, 2, 3)).toBe(6); - }); - it('should return the sum when arguments are provided one by one', () => { - const curriedSum = yd_function_curry(sum); - expect(curriedSum(1)(2)(3)).toBe(6); - }); - it('should return the sum when arguments are provided in parts', () => { - const curriedSum = yd_function_curry(sum); - expect(curriedSum(1, 2)(3)).toBe(6); - expect(curriedSum(1)(2, 3)).toBe(6); - }); - it('should work with different functions', () => { - const multiply = (a, b, c, d) => a * b * c * d; - const curriedMultiply = yd_function_curry(multiply); - expect(curriedMultiply(1, 2, 3, 4)).toBe(24); - expect(curriedMultiply(1)(2)(3)(4)).toBe(24); - expect(curriedMultiply(1, 2)(3, 4)).toBe(24); - }); - - it('should handle single argument functions', () => { - const identity = (x) => x; - const curriedIdentity = yd_function_curry(identity); - expect(curriedIdentity(42)).toBe(42); - }); -}); diff --git a/lib/helper/chain.js b/lib/helper/chain.js deleted file mode 100644 index e4fd803..0000000 --- a/lib/helper/chain.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * 链式调用函数 - * @author jay0815 - * @category helper - * @alias yd_helper_chain - * @param {...any} funcs 函数数组 - * @returns {function} 返回一个函数。 - * @summary 该函数接受任意数量的参数,并将这些参数依次传递给函数数组中的每个函数。 - * 第一个函数接收原始参数,后续函数接收前一个函数的返回值,最终返回最后一个函数的结果。 - * @example - * const add = (x) => x + 1; - * const multiply = (x) => x * 2; - * const subtract = (x) => x - 3; - * const chainedFunction = yd_helper_chain(add, multiply, subtract); - * console.log("调用链式函数并输出结果", chainedFunction(5)); // (5 + 1) * 2 - 3 = 9 - * @example - * const toUpperCase = (str) => str.toUpperCase(); - * const addExclamation = (str) => str + '!'; - * const repeat = (str) => str + str; - * const shout = yd_helper_chain(toUpperCase, addExclamation, repeat); - * console.log("调用链式函数并输出结果",shout('hello')); // "HELLO!HELLO!" - */ -export default (...funcs) => { - return (...args) => { - // 执行第一个函数,并将结果作为初始值传递给 reduce - return funcs.reduce( - (acc, fn, index) => { - if (typeof fn === 'function') { - // 如果是第一个函数,直接执行并返回结果作为初始值 - if (index === 0) { - return fn(...args); - } - // 对于后续的函数,使用前一个函数的结果作为参数 - return fn(acc); - } - throw new Error(`第${index}个参数必须是一个函数`); - }, - void 0 - ); - }; -}; diff --git a/lib/helper/chain.test.js b/lib/helper/chain.test.js deleted file mode 100644 index 0866388..0000000 --- a/lib/helper/chain.test.js +++ /dev/null @@ -1,49 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_helper_chain from './chain.js'; - -describe('yd_helper_chain test suit case', () => { - const add = (x) => x + 1; - const multiply = (x) => x * 2; - const subtract = (x) => x - 3; - // 测试基础的链式调用功能 - it('should perform basic chaining of functions', async (t) => { - const chainedFunction = yd_helper_chain(add, multiply, subtract); - expect(chainedFunction(5)).toBe(9); // (5 + 1) * 2 - 3 = 9 - }); - - // 测试字符串处理的链式调用 - it('should perform string transformations in sequence', async (t) => { - const toUpperCase = (str) => str.toUpperCase(); - const addExclamation = (str) => str + '!'; - const repeat = (str) => str + str; - const shout = yd_helper_chain(toUpperCase, addExclamation, repeat); - expect(shout('hello')).toBe('HELLO!HELLO!'); // hello -> HELLO -> HELLO! -> HELLO!HELLO! - }); - - // 测试无效输入(非函数类型)处理 - it('should throw an error if any of the inputs are not functions', () => { - const invalidChain = () => yd_helper_chain(add, null, subtract); - expect(invalidChain(1)).toThrowError('第1个参数必须是一个函数'); - }); - - // 测试没有输入函数的情况 - it('should return the undefined if no functions are provided', () => { - const identityChain = yd_helper_chain(); - expect(identityChain(10)).toBeUndefined(); - expect(identityChain('test')).toBeUndefined(); - }); - - // 测试多个参数输入的情况 - it('should handle functions with multiple arguments', () => { - const sum = (a, b) => a + b; - const square = (x) => x * x; - const sumAndSquare = yd_helper_chain(sum, square); - expect(sumAndSquare(2, 3)).toBe(25); // (2 + 3) ^ 2 = 25 - }); - - // 测试没有输入参数的情况 - it('should return undefined if no input arguments are provided', () => { - const chainedFunction = yd_helper_chain(add); - expect(chainedFunction()).toBeNaN(); // undefined + 1 = NaN - }); -}); diff --git a/lib/helper/debounce.js b/lib/helper/debounce.js deleted file mode 100644 index d4d53b9..0000000 --- a/lib/helper/debounce.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * 函数防抖 - * @author tank | dayDreamer-byte - * @category helper - * @alias yd_helper_debounce - * @param { function } fn 高频事件 - * @param { Number } delay 防抖延迟时间 默认1000 - * @param { Boolean } firstExecute 首次是否执行函数 - * @returns { function } 执行函数 - * @description 函数防抖:事件触发后设定一个等待延迟时间,如果在延迟时间内事件被再次触发,则重新计算延迟时间。在延迟时间内没有触发,则会在延迟时间到达后完成函数调用。 - */ -export default (fn, delay = 1000, firstExecute = false) => { - let timer = null; // 延迟执行器 - let isFuture = false; // 首次执行是否完成 - return function (...args) { - if (firstExecute && !isFuture) { - fn.apply(this, args); - isFuture = true; // 首次执行完毕 - } - timer && clearTimeout(timer); - const _this = this; - timer = setTimeout(() => { - fn.apply(_this, args); - }, delay); - }; -}; diff --git a/lib/helper/debounce.test.js b/lib/helper/debounce.test.js deleted file mode 100644 index bcc50aa..0000000 --- a/lib/helper/debounce.test.js +++ /dev/null @@ -1,41 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_helper_debounce from './debounce.js'; - -describe('yd_helper_debounce 测试套件', () => { - it('默认防抖测试', () => { - const debounceFn = yd_helper_debounce(() => {}, 1000); - expect(typeof debounceFn).toBe('function'); - }); - - it('在延时时间内多次调用确保只执行一次', (done) => { - let count = 0; - const debounceFn = yd_helper_debounce(() => { - count++; - }); - debounceFn(); - debounceFn(); - debounceFn(); - debounceFn(); - setTimeout(() => { - expect(count).toBe(1); - done(); - }, 2000); - }); - - it('首次执行立即执行', (done) => { - let count = 0; - const debounceFn = yd_helper_debounce( - () => { - count++; - }, - 1000, - true - ); - debounceFn(); - debounceFn(); - setTimeout(() => { - expect(count).toBe(2); - done(); - }, 2000); - }); -}); diff --git a/lib/helper/delay.js b/lib/helper/delay.js index 63f6b50..4e6c812 100644 --- a/lib/helper/delay.js +++ b/lib/helper/delay.js @@ -1,10 +1,11 @@ /** * 延迟函数 - * @author 陈随易 - * @category helper * @alias yd_helper_delay - * @param {Number} wait 等待时间 + * @category helper + * @param {number} wait 等待时间 * @returns {Promise} 返回延迟后的Promise + * @author 陈随易 + * @example yd_helper_delay() */ export default (wait) => { return new Promise((resolve) => { diff --git a/lib/helper/repeatExecute.js b/lib/helper/repeatExecute.js index 89a3463..cadd0bb 100644 --- a/lib/helper/repeatExecute.js +++ b/lib/helper/repeatExecute.js @@ -1,5 +1,3 @@ -import isFunction from '../is/function.js'; - /** * 重复执行函数 * @alias yd_helper_repeatExecute @@ -13,10 +11,6 @@ import isFunction from '../is/function.js'; * // 打印五次`execute!` 每次间隔1000ms */ export default async (fn, times, delay) => { - if (!isFunction(fn)) { - throw new Error('fn must be a function'); - } - if (times === 0) { return; } diff --git a/lib/helper/throttle.js b/lib/helper/throttle.js deleted file mode 100644 index 49ff0de..0000000 --- a/lib/helper/throttle.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * 函数节流 - * @author tank - * @category helper - * @alias yd_helper_throttle - * @param {function} fn 需要节流的函数 - * @param {Number} interval 时间间隔,单位为毫秒 (默认:300) - * @returns {function} 执行函数 - */ -export default (fn, interval) => { - let inThrottle; - interval = interval || 300; - return function () { - const args = arguments; - const that = this; - if (!inThrottle) { - fn.apply(that, args); - inThrottle = true; - setTimeout(() => (inThrottle = false), interval); - } - }; -}; diff --git a/lib/is/arrayContain.js b/lib/is/arrayContain.js index 7d17614..dd62ca0 100644 --- a/lib/is/arrayContain.js +++ b/lib/is/arrayContain.js @@ -1,11 +1,12 @@ /** * 判断数组是否有一个相同值 - * @author 陈随易 - * @category is * @alias yd_is_arrayContain + * @category is * @param {Array} arr1 数组1 * @param {Array} arr2 数组2 * @returns {Array} 返回两个数组是否至少有一个相同值 + * @author 陈随易 + * @example yd_is_arrayContain() */ export default (arr1, arr2) => { return arr1.some((element) => arr2.includes(element)); diff --git a/lib/is/boolean.js b/lib/is/boolean.js deleted file mode 100644 index 0627795..0000000 --- a/lib/is/boolean.js +++ /dev/null @@ -1,12 +0,0 @@ -import getValueType from '../internal/getValueType.js'; -/** - * 判断是否是布尔值 - * @author 陈随易 - * @category is - * @alias yd_is_boolean - * @param {any} value 任意值 - * @returns {Boolean} 返回是否是布尔值 - */ -export default (value) => { - return value === true || value === false || getValueType(value) === '[object Boolean]'; -}; diff --git a/lib/is/date.js b/lib/is/date.js deleted file mode 100644 index ec7d9ef..0000000 --- a/lib/is/date.js +++ /dev/null @@ -1,12 +0,0 @@ -import getValueType from '../internal/getValueType.js'; -/** - * 判断是否是日期 - * @author 陈随易 - * @category is - * @alias yd_is_date - * @param {any} value 任意值 - * @returns {Boolean} 返回是否是日期 - */ -export default (value) => { - return getValueType(value) === '[object Date]'; -}; diff --git a/lib/is/date.test.js b/lib/is/date.test.js deleted file mode 100644 index dfa130b..0000000 --- a/lib/is/date.test.js +++ /dev/null @@ -1,19 +0,0 @@ -import { it, expect, describe } from 'vitest'; -import yd_is_date from './date.js'; - -describe('yd_is_date', () => { - it('should return true for Date objects', () => { - expect(yd_is_date(new Date())).toBe(true); - }); - - it('should return false for objects that are not Date', () => { - expect(yd_is_date({})).toBe(false); - expect(yd_is_date([])).toBe(false); - expect(yd_is_date('2024-01-01')).toBe(false); // string - expect(yd_is_date('2024-01-01T00:00:00Z')).toBe(false); - expect(yd_is_date(1)).toBe(false); - expect(yd_is_date(null)).toBe(false); - expect(yd_is_date(undefined)).toBe(false); - expect(yd_is_date(true)).toBe(false); // boolean - }); -}); diff --git a/lib/is/empty.js b/lib/is/empty.js deleted file mode 100644 index 20d8178..0000000 --- a/lib/is/empty.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * 判断是否是空值 - * @author 陈随易 - * @category is - * @alias yd_is_empty - * @param {any} value 任意值 - * @returns {Boolean} 返回是否是空值 - */ -export default (value) => { - if (value === undefined || value === null) { - return true; - } - if (typeof value === 'string') { - return value.trim() === ''; - } - if (Array.isArray(value)) { - return value.length === 0; - } - if (typeof value === 'object') { - return Object.keys(value).length === 0; - } - return false; -}; diff --git a/lib/is/equal.js b/lib/is/equal.js deleted file mode 100644 index 50214d0..0000000 --- a/lib/is/equal.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * 深度比较两个值是否相等, 支持基本类型、对象、数组、日期对象, 不支持函数 - * @alias yd_is_equal - * @category is - * @param {*} a - * @param {*} b - * @returns {boolean} 返回比较结果 - * @author Amonduul - * @example - * yd_is_equal(1, 1); // true - * yd_is_equal(1, '1'); // false - * yd_is_equal(NaN, NaN); // true - * yd_is_equal({ a: 1 }, { a: 2 }); // false - */ - -export default function yd_is_equal(a, b) { - if (a === b) { - return true; - } - - // 处理 NaN 的特殊情况 - if (a !== a && b !== b) { - return true; - } - - const typeA = typeof a; - const typeB = typeof b; - if (typeA !== typeB) { - return false; - } - - if (typeA === 'function') { - throw new Error('yd_is_equal does not support function'); - } - - if (typeA === 'object' && a instanceof Date && b instanceof Date) { - return a.getTime() === b.getTime(); - } - - if (typeA === 'object') { - if ((a && !b) || (b && !a) || a.length !== b.length) { - return false; - } - const keysA = Object.keys(a); - const keysB = Object.keys(b); - - if (keysA.length !== keysB.length) { - return false; - } - - for (const key of keysA) { - if (!keysB.includes(key) || !yd_is_equal(a[key], b[key])) { - return false; - } - } - - return true; - } - - return false; -} diff --git a/lib/is/equal.test.js b/lib/is/equal.test.js deleted file mode 100644 index f47b046..0000000 --- a/lib/is/equal.test.js +++ /dev/null @@ -1,22 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_is_equal from './equal.js'; - -describe('yd_is_equal', () => { - it('should return true if two values are equal', () => { - expect(yd_is_equal(1, 1)).toBe(true); - expect(yd_is_equal('foo', 'foo')).toBe(true); - expect(yd_is_equal([1, 2, 3], [1, 2, 3])).toBe(true); - expect(yd_is_equal({ a: 1, b: 2 }, { a: 1, b: 2 })).toBe(true); - expect(yd_is_equal(new Date('2021-01-01'), new Date('2021-01-01'))).toBe(true); - expect(yd_is_equal(NaN, NaN)).toBe(true); - }); - - it('should return false if two values are not equal', () => { - expect(yd_is_equal(1, 2)).toBe(false); - expect(yd_is_equal('foo', 'bar')).toBe(false); - expect(yd_is_equal(undefined, null)).toBe(false); - expect(yd_is_equal(1, Object(1))).toBe(false); - expect(yd_is_equal([1, 2, 3], [1, 2, 4])).toBe(false); - expect(yd_is_equal({ a: 1, b: 2 }, { a: 1, b: 3 })).toBe(false); - }); -}); diff --git a/lib/is/float.js b/lib/is/float.js deleted file mode 100644 index d99cd31..0000000 --- a/lib/is/float.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * 判断是否是浮点数 - * @alias yd_is_float - * @category is - * @param {any} value 任意值 - * @returns {boolean} 返回是否是整数 - * @author 陈随易 - * @example - * yd_is_float(5.123) // false - * yd_is_float(5.0) // false - * yd_is_float(5) // false - */ -export default (value) => { - return typeof value === 'number' && value % 1 !== 0; -}; diff --git a/lib/is/float.test.js b/lib/is/float.test.js deleted file mode 100644 index e4f879b..0000000 --- a/lib/is/float.test.js +++ /dev/null @@ -1,31 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_is_float from './float.js'; - -describe('yd_is_float', () => { - it('should return `true` for arrays', () => { - expect(yd_is_float(1.23)).toBe(true); - }); - - it('should be return `false` for non-arrays', () => { - expect(yd_is_float({})).toBeFalsy(); - expect(yd_is_float({ 1: '1', length: 1 })).toBeFalsy(); - - expect(yd_is_float(123)).toBeFalsy(); - - expect(yd_is_float(`123`)).toBeFalsy(); - - expect(yd_is_float(true)).toBeFalsy(); - - expect(yd_is_float(Symbol())).toBeFalsy(); - - expect(yd_is_float(/a/)).toBeFalsy(); - - expect(yd_is_float(new Date())).toBeFalsy(); - - expect(yd_is_float(new Set())).toBeFalsy(); - - expect(yd_is_float(new Map())).toBeFalsy(); - - expect(yd_is_float(new Error())).toBeFalsy(); - }); -}); diff --git a/lib/is/function.js b/lib/is/function.js deleted file mode 100644 index 2928e10..0000000 --- a/lib/is/function.js +++ /dev/null @@ -1,13 +0,0 @@ -import getValueType from '../internal/getValueType.js'; -/** - * 判断是否是函数 - * @author 陈随易 - * @category is - * @alias yd_is_function - * @param {any} value 任意值 - * @returns {Boolean} 返回是否是函数 - */ -export default (value) => { - const tag = getValueType(value); - return tag === '[object Function]' || tag === '[object AsyncFunction]'; -}; diff --git a/lib/is/integer.js b/lib/is/integer.js deleted file mode 100644 index eb2c910..0000000 --- a/lib/is/integer.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * 判断是否是整数 - * @alias yd_is_integer - * @category is - * @param {any} value 任意值 - * @returns {boolean} 返回是否是整数 - * @author 陈随易 - * @example yd_is_integer(1) // true - */ -export default (value) => { - return Number.isInteger(value) && value.toString().indexOf('.') === -1; -}; diff --git a/lib/is/map.js b/lib/is/map.js deleted file mode 100644 index 5bd26be..0000000 --- a/lib/is/map.js +++ /dev/null @@ -1,12 +0,0 @@ -import getValueType from '../internal/getValueType.js'; -/** - * 判断是否是Map值 - * @author 陈随易 - * @category is - * @alias yd_is_map - * @param {any} value 任意值 - * @returns {Boolean} 返回是否是Map值 - */ -export default (value) => { - return getValueType(value) === '[object Map]'; -}; diff --git a/lib/is/null.js b/lib/is/null.js deleted file mode 100644 index 3106921..0000000 --- a/lib/is/null.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * 判断是否是Null值 - * @author 陈随易 - * @category is - * @alias yd_is_null - * @param {any} value 任意值 - * @returns {Boolean} 返回是否是Null值 - */ -export default (value) => { - return value === null; -}; diff --git a/lib/is/number.js b/lib/is/number.js deleted file mode 100644 index 46808b7..0000000 --- a/lib/is/number.js +++ /dev/null @@ -1,14 +0,0 @@ -import getValueType from '../internal/getValueType.js'; - -/** - * 判断是否是数字 - * @alias yd_is_number - * @category is - * @param {any} value 任意值 - * @returns {boolean} 返回是否是数字 - * @author 陈随易 - * @example yd_is_number(123) // true - */ -export default (value) => { - return getValueType(value) === '[object Number]' && !isNaN(value); -}; diff --git a/lib/is/object.js b/lib/is/object.js deleted file mode 100644 index ee81620..0000000 --- a/lib/is/object.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * 判断是否是Object值 - * @alias yd_is_object - * @category is - * @param {any} value 任意值 - * @returns {boolean} 返回是否是Object值 - * @author 陈随易 - * @example yd_is_object({}) // true - */ -export default (value) => { - return value !== null && typeof value === 'object' && Object.prototype.toString.call(value) === '[object Object]'; -}; diff --git a/lib/is/odd.js b/lib/is/odd.js deleted file mode 100644 index ce91cbb..0000000 --- a/lib/is/odd.js +++ /dev/null @@ -1,18 +0,0 @@ -import yd_is_number from './number.js'; - -/** - * 判断是否是奇数 - * @alias yd_is_odd - * @category is - * @param {any} value 任意值 - * @returns {boolean} 返回是否是奇数 - * @author imddc https://github.com/imddc - * @example yd_is_odd(123) // true - */ -export default (value) => { - if (!yd_is_number(value)) { - throw new Error('value must be a number'); - } - - return value % 2 === 1 || value % 2 === -1; -}; diff --git a/lib/is/odd.test.js b/lib/is/odd.test.js deleted file mode 100644 index 15f4c48..0000000 --- a/lib/is/odd.test.js +++ /dev/null @@ -1,24 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import yd_is_odd from './odd'; - -describe('yd_is_odd', () => { - it('should be `true`', () => { - expect(yd_is_odd(13)).toBeTruthy(); - expect(yd_is_odd(-13)).toBeTruthy(); - }); - - it('should be `false`', () => { - expect(yd_is_odd(0)).toBeFalsy(); - expect(yd_is_odd(2)).toBeFalsy(); - expect(yd_is_odd(-2)).toBeFalsy(); - }); - - it('should throw Error', () => { - expect(() => yd_is_odd(true)).toThrowError('value must be a number'); - expect(() => yd_is_odd(Symbol(''))).toThrowError('value must be a number'); - expect(() => yd_is_odd([])).toThrowError('value must be a number'); - expect(() => yd_is_odd({})).toThrowError('value must be a number'); - expect(() => yd_is_odd(new Date())).toThrowError('value must be a number'); - // ... - }); -}); diff --git a/lib/is/phone.js b/lib/is/phone.js deleted file mode 100644 index 432eace..0000000 --- a/lib/is/phone.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * 判断是否是手机号 - * @author 杜同学 - * @category is - * @alias yd_is_phone - * @param {any} value 任意值 - * @returns {Boolean} 返回是否是手机号 - */ -export default (value) => { - const phoneRegex = /^1[3-9]\d{9}$/; - return phoneRegex.test(value); -}; diff --git a/lib/is/plainObject.js b/lib/is/plainObject.js deleted file mode 100644 index f7d4562..0000000 --- a/lib/is/plainObject.js +++ /dev/null @@ -1,20 +0,0 @@ -import yd_is_object from './object.js'; -/** - * 判断是否是空对象 - * @alias yd_is_plainObject - * @category is - * @param {any} value 任意值 - * @returns {boolean} 返回是否是空对象 - * @author 陈随易 - * @example yd_is_plainObject({}) // true - */ -export default (value) => { - if (yd_is_object(value) === false) { - return false; - } - - // const prototype = Object.getPrototypeOf(value); - // return !!prototype && prototype.constructor === Object && prototype === Object.prototype; - const result = Object.keys(value).length === 0; - return result; -}; diff --git a/lib/is/plainObject.test.js b/lib/is/plainObject.test.js deleted file mode 100644 index 0ceeb8f..0000000 --- a/lib/is/plainObject.test.js +++ /dev/null @@ -1,13 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import yd_is_plainObject from './plainObject.js'; - -describe('yd_is_plainObject', () => { - it('should be `true`', () => { - expect(yd_is_plainObject({})).toBe(true); - }); - - it('should be `false`', () => { - expect(yd_is_plainObject({ a: 1 })).toBe(false); - expect(yd_is_plainObject(null)).toBe(false); - }); -}); diff --git a/lib/is/regexp.js b/lib/is/regexp.js deleted file mode 100644 index b057f74..0000000 --- a/lib/is/regexp.js +++ /dev/null @@ -1,12 +0,0 @@ -import getValueType from '../internal/getValueType.js'; -/** - * 判断是否是正则表达式 - * @author 陈随易 - * @category is - * @alias yd_is_regexp - * @param {any} value 任意值 - * @returns {Boolean} 返回是否是正则表达式 - */ -export default (value) => { - return getValueType(value) === '[object RegExp]'; -}; diff --git a/lib/is/set.js b/lib/is/set.js deleted file mode 100644 index 99a0b33..0000000 --- a/lib/is/set.js +++ /dev/null @@ -1,12 +0,0 @@ -import getValueType from '../internal/getValueType.js'; -/** - * 判断是否是Set值 - * @author 陈随易 - * @category is - * @alias yd_is_set - * @param {any} value 任意值 - * @returns {Boolean} 返回是否是Set值 - */ -export default (value) => { - return getValueType(value) === '[object Set]'; -}; diff --git a/lib/is/string.js b/lib/is/string.js deleted file mode 100644 index cd33854..0000000 --- a/lib/is/string.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * 判断是否是字符串 - * @author 陈随易 - * @category is - * @alias yd_is_string - * @param {any} value 任意值 - * @returns {Boolean} 返回是否是字符串 - */ -export default (value) => { - return Object.prototype.toString.call(value) === '[object String]'; -}; diff --git a/lib/is/symbol.js b/lib/is/symbol.js deleted file mode 100644 index 556e47b..0000000 --- a/lib/is/symbol.js +++ /dev/null @@ -1,12 +0,0 @@ -import getValueType from '../internal/getValueType.js'; -/** - * 判断是否是Symbol值 - * @author 陈随易 - * @category is - * @alias yd_is_symbol - * @param {any} value 任意值 - * @returns {Boolean} 返回是否是Symbol值 - */ -export default (value) => { - return getValueType(value) === '[object Symbol]'; -}; diff --git a/lib/is/undefined.js b/lib/is/undefined.js deleted file mode 100644 index f130ee2..0000000 --- a/lib/is/undefined.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * 判断是否是Undefined - * @author 陈随易 - * @category is - * @alias yd_is_undefined - * @param {any} value 任意值 - * @returns {Boolean} 返回是否是Undefined值 - */ -export default (value) => { - return value === undefined; -}; diff --git a/lib/is/weakMap.js b/lib/is/weakMap.js deleted file mode 100644 index bbab82c..0000000 --- a/lib/is/weakMap.js +++ /dev/null @@ -1,12 +0,0 @@ -import getValueType from '../internal/getValueType.js'; -/** - * 判断是否是WeakMap值 - * @author 陈随易 - * @category is - * @alias yd_is_weakMap - * @param {any} value 任意值 - * @returns {Boolean} 返回是否是WeakMap值 - */ -export default (value) => { - return getValueType(value) === '[object WeakMap]'; -}; diff --git a/lib/is/weakSet.js b/lib/is/weakSet.js deleted file mode 100644 index faf371f..0000000 --- a/lib/is/weakSet.js +++ /dev/null @@ -1,12 +0,0 @@ -import getValueType from '../internal/getValueType.js'; -/** - * 判断是否是WeakSet值 - * @author 陈随易 - * @category is - * @alias yd_is_weakSet - * @param {any} value 任意值 - * @returns {Boolean} 返回是否是WeakSet值 - */ -export default (value) => { - return getValueType(value) === '[object WeakSet]'; -}; diff --git a/lib/is/workday.js b/lib/is/workday.js deleted file mode 100644 index 45f3b8f..0000000 --- a/lib/is/workday.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * 检查日期是否为工作日 (周一到周五为工作日, 周六周日为节假日) - * @author 生命过客 <739694218@qq.com> - * @category is - * @alias yd_is_workDay - * @param {Date} date 日期 - * @returns {Boolean} 周一到周五为工作日, 周六周日为节假日 - * @summary 此方法只能检测自然工作日,无法检测国家法定节假日, 类似清明,端午,中秋,国庆这类节日需要调假日办的api获取才能判断 - */ -export default (date) => { - return date.getDay() % 6 !== 0; -}; diff --git a/lib/object/deepClone.js b/lib/object/deepClone.js deleted file mode 100644 index 41e72f7..0000000 --- a/lib/object/deepClone.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * 深度克隆 - * @author alvis - * @category object - * @alias yd_object_deepClone - * @param {any} value 需要克隆的值 - * @returns {Any} 返回深度克隆值 - */ -export default (value) => { - // 缓存 - const cache = new Map(); - - function _deepClone(value) { - // 判断是否是对象,不是对象直接返回对应得值 - if (typeof value !== 'object' || value === null) { - return value; - } - // 查看缓存中是否存在。缓存中存在,直接在缓存中取 - if (cache.has(value)) { - return cache.get(value); - } - // 区分对象和数组 - const result = Array.isArray(value) ? [] : {}; - // 设置缓存 - cache.set(value, result); - for (const key in value) { - result[key] = _deepClone(value[key]); - } - return result; - } - return _deepClone(value); -}; diff --git a/lib/object/mapKeys.js b/lib/object/mapKeys.js deleted file mode 100644 index c1c58d0..0000000 --- a/lib/object/mapKeys.js +++ /dev/null @@ -1,36 +0,0 @@ -import isObject from '../is/object.js'; -import isFunction from '../is/function.js'; - -/** - * batch modify the key of the object. - * @alias yd_object_mapKeys - * @category object - * @param {object} obj origin object - * @param {(value: any, key: string, obj: object) => string} fn how to modify the key - * @returns {object} new object - * @author imddc - * @example - mapKeys({ a: 1, b: '2', c: 3 }, (_, key) => key + 1) // { a1: 1, b1: '2', c1: 3 } - */ -export default (obj, fn) => { - if (!isObject(obj)) { - throw new Error('obj must be an object'); - } - - if (!isFunction(fn)) { - throw new Error('fn must be an function'); - } - - if (Object.keys(obj).length === 0) { - return obj; - } - - const result = {}; - for (const key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key)) { - const value = obj[key]; - result[fn(value, key, obj)] = value; - } - } - return result; -}; diff --git a/lib/object/mapKeys.test.js b/lib/object/mapKeys.test.js deleted file mode 100644 index 9968338..0000000 --- a/lib/object/mapKeys.test.js +++ /dev/null @@ -1,22 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import mapKeys from './mapKeys'; - -describe('pickBy', () => { - it('should return `key + 1` member', () => { - const obj = { a: 1, b: '2', c: 3 }; - const res = { a1: 1, b1: '2', c1: 3 }; - expect(mapKeys(obj, (_, key) => key + 1)).toEqual(res); - }); - - it('should return Empty member', () => { - const obj = {}; - const res = {}; - expect(mapKeys(obj, (_, key) => key)).toEqual(res); - }); - - it('should throw Error', () => { - expect(() => mapKeys([], (_) => _)).toThrow('obj must be an object'); - - expect(() => mapKeys({ a: 1, b: 2, c: 3 }, {})).toThrow('fn must be an function'); - }); -}); diff --git a/lib/object/merge.js b/lib/object/merge.js deleted file mode 100644 index 9e62bd9..0000000 --- a/lib/object/merge.js +++ /dev/null @@ -1,69 +0,0 @@ -function isPlainObject(payload) { - if (Object.prototype.toString.call(payload).slice(8, -1) !== 'Object') return false; - const prototype = Object.getPrototypeOf(payload); - return !!prototype && prototype.constructor === Object && prototype === Object.prototype; -} -function isSymbol(payload) { - return Object.prototype.toString.call(payload).slice(8, -1) === 'Symbol'; -} -function assignProp(carry, key, newVal, originalObject) { - const propType = {}.propertyIsEnumerable.call(originalObject, key) ? 'enumerable' : 'nonenumerable'; - if (propType === 'enumerable') carry[key] = newVal; - if (propType === 'nonenumerable') { - Object.defineProperty(carry, key, { - value: newVal, - enumerable: false, - writable: true, - configurable: true - }); - } -} -function mergeRecursively(origin, newComer, compareFn) { - // always return newComer if its not an object - if (!isPlainObject(newComer)) return newComer; - // define newObject to merge all values upon - let newObject = {}; - if (isPlainObject(origin)) { - const props = Object.getOwnPropertyNames(origin); - const symbols = Object.getOwnPropertySymbols(origin); - newObject = [...props, ...symbols].reduce((carry, key) => { - const targetVal = origin[key]; - if ((!isSymbol(key) && !Object.getOwnPropertyNames(newComer).includes(key)) || (isSymbol(key) && !Object.getOwnPropertySymbols(newComer).includes(key))) { - assignProp(carry, key, targetVal, origin); - } - return carry; - }, {}); - } - // newObject has all properties that newComer hasn't - const props = Object.getOwnPropertyNames(newComer); - const symbols = Object.getOwnPropertySymbols(newComer); - const result = [...props, ...symbols].reduce((carry, key) => { - // re-define the origin and newComer as targetVal and newVal - let newVal = newComer[key]; - const targetVal = isPlainObject(origin) ? origin[key] : undefined; - // When newVal is an object do the merge recursively - if (targetVal !== undefined && isPlainObject(newVal)) { - newVal = mergeRecursively(targetVal, newVal, compareFn); - } - const propToAssign = compareFn ? compareFn(targetVal, newVal, key) : newVal; - assignProp(carry, key, propToAssign, newComer); - return carry; - }, newObject); - return result; -} - -/** - * 合并对象 - * @alias yd_object_merge - * @category object - * @param {object} target 目标对象 - * @param {...any} otherObjects 其他对象 - * @returns {object} 返回合并后的对象 - * @author https://github.com/mesqueeb/merge-anything - * @example yd_object_merge({a:1,b:[2,3],c:{d:4}},{a:2,b:[4,5],c:{e:6}}) // {a:2,b:[4,5],c:{d:4,e:6}} - */ -export default (target, ...otherObjects) => { - return otherObjects.reduce((result, newComer) => { - return mergeRecursively(result, newComer); - }, target); -}; diff --git a/lib/object/merge.test.js b/lib/object/merge.test.js deleted file mode 100644 index d6f44c9..0000000 --- a/lib/object/merge.test.js +++ /dev/null @@ -1,15 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_object_merge from './merge.js'; - -describe('yd_object_merge', () => { - it('should return true', () => { - const target = { a: 1, b: [2, 3], c: { d: 4 } }; - const source = { a: 2, b: [4, 5], c: { e: 6 } }; - expect(yd_object_merge(target, source)).toStrictEqual({ a: 2, b: [4, 5], c: { d: 4, e: 6 } }); - }); - it('should return true', () => { - const target = { a: 1, b: 2, c: { d: 4 } }; - const source = { e: 2, f: [4, 5], g: { h: 6 } }; - expect(yd_object_merge(target, source)).toStrictEqual({ a: 1, b: 2, c: { d: 4 }, e: 2, f: [4, 5], g: { h: 6 } }); - }); -}); diff --git a/lib/object/mergeAndConcat.js b/lib/object/mergeAndConcat.js deleted file mode 100644 index 2935e04..0000000 --- a/lib/object/mergeAndConcat.js +++ /dev/null @@ -1,81 +0,0 @@ -import yd_is_array from '../is/array.js'; - -function isPlainObject(payload) { - if (Object.prototype.toString.call(payload).slice(8, -1) !== 'Object') return false; - const prototype = Object.getPrototypeOf(payload); - return !!prototype && prototype.constructor === Object && prototype === Object.prototype; -} -function isSymbol(payload) { - return Object.prototype.toString.call(payload).slice(8, -1) === 'Symbol'; -} - -const concatArrays = (originVal, newVal) => { - if (yd_is_array(originVal) && yd_is_array(newVal)) { - // concat logic - return originVal.concat(newVal); - } - return newVal; // always return newVal as fallback!! -}; - -const assignProp = (carry, key, newVal, originalObject) => { - const propType = {}.propertyIsEnumerable.call(originalObject, key) ? 'enumerable' : 'nonenumerable'; - if (propType === 'enumerable') carry[key] = newVal; - if (propType === 'nonenumerable') { - Object.defineProperty(carry, key, { - value: newVal, - enumerable: false, - writable: true, - configurable: true - }); - } -}; - -const mergeRecursively = (origin, newComer, compareFn) => { - // always return newComer if its not an object - if (!isPlainObject(newComer)) return newComer; - // define newObject to merge all values upon - let newObject = {}; - if (isPlainObject(origin)) { - const props = Object.getOwnPropertyNames(origin); - const symbols = Object.getOwnPropertySymbols(origin); - newObject = [...props, ...symbols].reduce((carry, key) => { - const targetVal = origin[key]; - if ((!isSymbol(key) && !Object.getOwnPropertyNames(newComer).includes(key)) || (isSymbol(key) && !Object.getOwnPropertySymbols(newComer).includes(key))) { - assignProp(carry, key, targetVal, origin); - } - return carry; - }, {}); - } - // newObject has all properties that newComer hasn't - const props = Object.getOwnPropertyNames(newComer); - const symbols = Object.getOwnPropertySymbols(newComer); - const result = [...props, ...symbols].reduce((carry, key) => { - // re-define the origin and newComer as targetVal and newVal - let newVal = newComer[key]; - const targetVal = isPlainObject(origin) ? origin[key] : undefined; - // When newVal is an object do the merge recursively - if (targetVal !== undefined && isPlainObject(newVal)) { - newVal = mergeRecursively(targetVal, newVal, compareFn); - } - const propToAssign = compareFn ? compareFn(targetVal, newVal, key) : newVal; - assignProp(carry, key, propToAssign, newComer); - return carry; - }, newObject); - return result; -}; - -/** - * 合并对象 - * @alias yd_object_mergeAndConcat - * @category object - * @param {object} target 目标对象 - * @param {...any} otherObjects 其他对象 - * @returns {object} 返回合并后的对象 - * @author https://github.com/mesqueeb/merge-anything - * @example yd_object_mergeAndConcat({a:1,b:[2,3],c:{d:4}},{a:2,b:[4,5],c:{e:6}}) // {a:2,b:[2,3,4,5],c:{d:4,e:6}} - */ -export default (target, ...otherObjects) => { - return otherObjects.reduce((result, newComer) => { - return mergeRecursively(result, newComer, concatArrays); - }, target); -}; diff --git a/lib/object/mergeAndConcat.test.js b/lib/object/mergeAndConcat.test.js deleted file mode 100644 index badc6a9..0000000 --- a/lib/object/mergeAndConcat.test.js +++ /dev/null @@ -1,10 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_object_mergeAndConcat from './mergeAndConcat.js'; - -describe('yd_object_mergeAndConcat', () => { - it('should return true', () => { - const target = { a: 1, b: [2, 3], c: { d: 4 } }; - const source = { a: 2, b: [4, 5], c: { e: 6 } }; - expect(yd_object_mergeAndConcat(target, source)).toStrictEqual({ a: 2, b: [2, 3, 4, 5], c: { d: 4, e: 6 } }); - }); -}); diff --git a/lib/object/omit.js b/lib/object/omit.js deleted file mode 100644 index 2aa749c..0000000 --- a/lib/object/omit.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * 对象属性排除 - * @author 陈随易 - * @category object - * @alias yd_object_omit - * @param {Object} obj 对象数据 - * @param {Array} fields 要排除的字段数组 - * @returns {Object} 返回排除部分属性后的对象 - */ -export default (obj, fields = []) => { - const result = Object.create(null); - for (let key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key) && fields.includes(key) === false) { - result[key] = obj[key]; - } - } - return result; -}; diff --git a/lib/object/pick.js b/lib/object/pick.js deleted file mode 100644 index 40af8d2..0000000 --- a/lib/object/pick.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * 对象属性摘取 - * @author 陈随易 - * @category object - * @alias yd_object_pick - * @param {Object} obj 对象数据 - * @param {Array} fields 字段数组 - * @returns {Object} 摘取对象中的指定字段 - */ -export default (obj, fields = []) => { - const picked = {}; - for (const key of fields) { - if (Object.prototype.hasOwnProperty.call(obj, key)) { - picked[key] = obj[key]; - } - } - return picked; -}; diff --git a/lib/object/pickBy.js b/lib/object/pickBy.js deleted file mode 100644 index b2f8d10..0000000 --- a/lib/object/pickBy.js +++ /dev/null @@ -1,36 +0,0 @@ -import isObject from '../is/object.js'; -import isFunction from '../is/function.js'; - -/** - * 对象属性摘取 - * @alias yd_object_pickBy - * @category object - * @param {object} obj 对象数据 - * @param {Function} fn 获取字段的方式 - * @returns {object} 摘取对象中的指定字段 - * @author imddc - * @example yd_object_pickBy() - */ -export default (obj, fn) => { - if (!isObject(obj)) { - throw new Error('obj must be an object'); - } - - if (!isFunction(fn)) { - throw new Error('fn must be an function'); - } - - if (Object.keys(obj).length === 0) { - return obj; - } - - const picked = {}; - for (const key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key)) { - if (fn(obj[key])) { - picked[key] = obj[key]; - } - } - } - return picked; -}; diff --git a/lib/object/pickBy.test.js b/lib/object/pickBy.test.js deleted file mode 100644 index 010a2d1..0000000 --- a/lib/object/pickBy.test.js +++ /dev/null @@ -1,30 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import pickBy from './pickBy.js'; -import isNumber from '../is/number.js'; -import isBoolean from '../is/boolean.js'; - -describe('pickBy', () => { - it('should return number member', () => { - const obj = { a: 1, b: '2', c: 3 }; - const res = { a: 1, c: 3 }; - expect(pickBy(obj, isNumber)).toEqual(res); - }); - - it('should return Boolean member', () => { - const obj = { a: true, b: '2', c: 3, d: false, e: undefined, f: null, g: Symbol(), h: {}, i: [] }; - const res = { a: true, d: false }; - expect(pickBy(obj, isBoolean)).toEqual(res); - }); - - it('should return Empty member', () => { - const obj = {}; - const res = {}; - expect(pickBy(obj, (_) => _)).toEqual(res); - }); - - it('should throw Error', () => { - expect(() => pickBy([], (_) => _)).toThrow('obj must be an object'); - - expect(() => pickBy({ a: 1, b: 2, c: 3 }, {})).toThrow('fn must be an function'); - }); -}); diff --git a/lib/object/queryParams.js b/lib/object/queryParams.js new file mode 100644 index 0000000..40df0e4 --- /dev/null +++ b/lib/object/queryParams.js @@ -0,0 +1,22 @@ +/** + * 对象拼接查询参数 + * @alias yd_object_queryParams + * @category object + * @param {object} obj 对象数据 + * @param {Array} explude 排除字段数组 + * @returns {object} 摘取对象中的指定字段 + * @author 陈随易 + * @example yd_object_queryParams() + */ +export default (obj, explude = [null, undefined]) => { + const paramsPair = []; + for (let key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + if (explude.includes(key) === false) { + paramsPair.push(`${key}=${obj[key]}`); + } + } + } + const queryParams = paramsPair.join('&'); + return queryParams; +}; diff --git a/lib/string/camelCase.js b/lib/string/camelCase.js deleted file mode 100644 index efe1491..0000000 --- a/lib/string/camelCase.js +++ /dev/null @@ -1,32 +0,0 @@ -import capitalize from './capitalize.js'; - -const camel = (str) => { - const parts = - str - ?.replace(/([A-Z])+/g, capitalize) - ?.split(/(?=[A-Z])|[.\-\s_]/) - .map((x) => x.toLowerCase()) ?? []; - if (parts.length === 0) return ''; - if (parts.length === 1) return parts[0]; - return parts.reduce((acc, part) => { - return `${acc}${part.charAt(0).toUpperCase()}${part.slice(1)}`; - }); -}; - -/** - * 字符串转小驼峰风格 - * @author 陈随易 - * @category string - * @alias yd_string_camelCase - * @param {String} value 字符串数据 - * @param {String} delimiter 分隔符 - * @returns {String} 返回小驼峰风格的字符串 - */ -export default (value, delimiter = '/') => { - if (value === undefined || value === null || value === '') return value; - const data = value - .split(delimiter) - .map((v) => camel(v)) - .join(delimiter); - return data; -}; diff --git a/lib/string/capitalize.js b/lib/string/capitalize.js deleted file mode 100644 index 8bceb82..0000000 --- a/lib/string/capitalize.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * 字符串首字母大写 - * @author 陈随易 - * @category string - * @alias yd_string_capitalize - * @param {String} value 字符串数据 - * @param {String} delimiter 分隔符 - * @returns {String} 返回首字母大写的字符串 - */ -export default (str) => { - if (!str || str.length === 0) return ''; - const lower = str.toLowerCase(); - return lower.substring(0, 1).toUpperCase() + lower.substring(1, lower.length); -}; diff --git a/lib/string/kebabCase.js b/lib/string/kebabCase.js deleted file mode 100644 index d7547e0..0000000 --- a/lib/string/kebabCase.js +++ /dev/null @@ -1,32 +0,0 @@ -import capitalize from './capitalize.js'; - -const kebab = (str) => { - const parts = - str - ?.replace(/([A-Z])+/g, capitalize) - ?.split(/(?=[A-Z])|[.\-\s_]/) - .map((x) => x.toLowerCase()) ?? []; - if (parts.length === 0) return ''; - if (parts.length === 1) return parts[0]; - return parts.reduce((acc, part) => { - return `${acc}-${part.toLowerCase()}`; - }); -}; - -/** - * 字符串转中划线风格 - * @author 陈随易 - * @category string - * @alias yd_string_kebabCase - * @param {String} value 字符串数据 - * @param {String} delimiter 分隔符 - * @returns {String} 返回中划线风格的字符串 - */ -export default (value, delimiter = '/') => { - if (value === undefined || value === null || value === '') return value; - const data = value - .split(delimiter) - .map((v) => kebab(v)) - .join(delimiter); - return data; -}; diff --git a/lib/string/snakeCase.js b/lib/string/snakeCase.js deleted file mode 100644 index f1ccb77..0000000 --- a/lib/string/snakeCase.js +++ /dev/null @@ -1,25 +0,0 @@ -import capitalize from './capitalize.js'; - -/** - * 字符串转蛇形风格 - * @author 陈随易 - * @category string - * @alias yd_string_snakeCase - * @param {String} value 字符串数据 - * @param {String} delimiter 分隔符 - * @returns {String} 返回蛇型风格的字符串 - */ - -export default (str, splitOnNumber = true) => { - const parts = - str - ?.replace(/([A-Z])+/g, capitalize) - .split(/(?=[A-Z])|[.\-\s_]/) - .map((x) => x.toLowerCase()) ?? []; - if (parts.length === 0) return ''; - if (parts.length === 1) return parts[0]; - const result = parts.reduce((acc, part) => { - return `${acc}_${part.toLowerCase()}`; - }); - return splitOnNumber === false ? result : result.replace(/([A-Za-z]{1}[0-9]{1})/, (val) => `${val[0]}_${val[1]}`); -}; diff --git a/lib/tree/traverse.js b/lib/tree/traverse.js index fa2fc47..89e7fe8 100644 --- a/lib/tree/traverse.js +++ b/lib/tree/traverse.js @@ -1,11 +1,12 @@ /** * 数结构遍历函数 - * @author 陈随易 - * @category tree * @alias yd_tree_traverse + * @category tree * @param {Array} tree 树结构数据 * @param {Function} mapFunction 迭代函数 * @returns {Function} 树结构迭代 + * @author 陈随易 + * @example yd_tree_traverse() */ export default (tree, mapFunction) => { function preorder(node, index, parent) { diff --git a/lib/unit/_meta.json b/lib/unit/_meta.json new file mode 100644 index 0000000..3a7552e --- /dev/null +++ b/lib/unit/_meta.json @@ -0,0 +1,4 @@ +{ + "name": "单位", + "describe": "单位转换" +} diff --git a/lib/unit/byteSize.js b/lib/unit/byteSize.js new file mode 100644 index 0000000..3251929 --- /dev/null +++ b/lib/unit/byteSize.js @@ -0,0 +1,33 @@ +/** + * 计算机存储单位互相转换 + * @alias yd_unit_byteSize + * @category unit + * @param {number} value 大小值 + * @param {string} fromUnit 大小单位 + * @param {string} toUnit 转换单位 + * @returns {string} 格式化后的文件大小,包含单位 + * @author 陈随易 + * @example yd_unit_byteSize() + */ +export default (value, fromUnit, toUnit) => { + const units = ['b', 'B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + const bitUnits = ['b', 'Kb', 'Mb', 'Gb', 'Tb', 'Pb', 'Eb', 'Zb', 'Yb']; + + let fromIndex = units.indexOf(fromUnit); + let toIndex = units.indexOf(toUnit); + + if (fromIndex === -1) fromIndex = bitUnits.indexOf(fromUnit); + if (toIndex === -1) toIndex = bitUnits.indexOf(toUnit); + + if (fromIndex === -1 || toIndex === -1) { + throw new Error('无效的单位'); + } + + const bitsToBytesOffset = fromUnit === 'b' ? -1 : 0; + const bytesToBitsOffset = toUnit === 'b' ? 1 : 0; + + const totalOffset = toIndex - fromIndex + bitsToBytesOffset + bytesToBitsOffset; + const result = value * Math.pow(1024, -totalOffset); + + return parseFloat(result.toFixed(2)); +}; diff --git a/lib/browser/getQueryParams.js b/lib/url/getQueryParams.js similarity index 100% rename from lib/browser/getQueryParams.js rename to lib/url/getQueryParams.js diff --git a/libBrowser/tool/_meta.json b/libBrowser/tool/_meta.json new file mode 100644 index 0000000..4a3fe85 --- /dev/null +++ b/libBrowser/tool/_meta.json @@ -0,0 +1,4 @@ +{ + "name": "工具", + "describe": "全屏、下载、元素查找、截图等网页工具函数" +} diff --git a/lib/browser/copyText.js b/libBrowser/tool/copyText.js similarity index 100% rename from lib/browser/copyText.js rename to libBrowser/tool/copyText.js index f462b60..b2f80e5 100644 --- a/lib/browser/copyText.js +++ b/libBrowser/tool/copyText.js @@ -1,10 +1,10 @@ /** * 复制文本 - * @author ssyamv https://github.com/ssyamv + * @alias yd_browser_copyText * @category browser * @param {string} text 要复制的文本 * @returns {Promise} 是否复制成功 - * @alias yd_browser_copyText + * @author ssyamv https://github.com/ssyamv * @example yd_browser_copyText('123456'); */ export default async (text) => { diff --git a/lib/browser/exitFullScreen.js b/libBrowser/tool/exitFullScreen.js similarity index 100% rename from lib/browser/exitFullScreen.js rename to libBrowser/tool/exitFullScreen.js diff --git a/lib/browser/getScrollBarSize.js b/libBrowser/tool/getScrollBarSize.js similarity index 100% rename from lib/browser/getScrollBarSize.js rename to libBrowser/tool/getScrollBarSize.js diff --git a/lib/browser/irregularSorting.js b/libBrowser/tool/irregularSorting.js similarity index 100% rename from lib/browser/irregularSorting.js rename to libBrowser/tool/irregularSorting.js diff --git a/lib/browser/isElementInViewport.js b/libBrowser/tool/isElementInViewport.js similarity index 100% rename from lib/browser/isElementInViewport.js rename to libBrowser/tool/isElementInViewport.js diff --git a/lib/browser/openFullscreen.js b/libBrowser/tool/openFullscreen.js similarity index 100% rename from lib/browser/openFullscreen.js rename to libBrowser/tool/openFullscreen.js diff --git a/lib/browser/openWindow.js b/libBrowser/tool/openWindow.js similarity index 69% rename from lib/browser/openWindow.js rename to libBrowser/tool/openWindow.js index bd1cb1d..2c2e020 100644 --- a/lib/browser/openWindow.js +++ b/libBrowser/tool/openWindow.js @@ -1,33 +1,29 @@ /** * 在当前页面打开新窗口页 - * @author 王勇 - * @category browser * @alias yd_browser_openWindow + * @category browser * @param {string} url 打开的网页地址 * @param {string} title 打开的网页标题 * @param {number} width 打开网页的宽度 * @param {number} height 打开网页的高度 * @returns {Window | null} 新打开的窗口对象,或在失败时返回 null + * @author 王勇 */ export default (url, title, width, height) => { // 获取屏幕位置和尺寸 - const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left - const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top + const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left; + const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top; - const screenWidth = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width - const screenHeight = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height + const screenWidth = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width; + const screenHeight = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height; // 计算窗口位置以居中显示 - const left = ((screenWidth / 2) - (width / 2)) + dualScreenLeft - const top = ((screenHeight / 2) - (height / 2)) + dualScreenTop + const left = screenWidth / 2 - width / 2 + dualScreenLeft; + const top = screenHeight / 2 - height / 2 + dualScreenTop; // 打开新窗口 - const newWindow = window.open( - url, - title, - `toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=${width}, height=${height}, top=${top}, left=${left}` - ); + const newWindow = window.open(url, title, `toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=${width}, height=${height}, top=${top}, left=${left}`); // 如果可能,将焦点放在新窗口上 if (newWindow && typeof newWindow.focus === 'function') { @@ -35,4 +31,4 @@ export default (url, title, width, height) => { } return newWindow; -} +}; diff --git a/lib/browser/scrollTo.js b/libBrowser/tool/scrollTo.js similarity index 100% rename from lib/browser/scrollTo.js rename to libBrowser/tool/scrollTo.js diff --git a/lib/browser/scrollToTop.js b/libBrowser/tool/scrollToTop.js similarity index 96% rename from lib/browser/scrollToTop.js rename to libBrowser/tool/scrollToTop.js index 18d0e21..19a25f1 100644 --- a/lib/browser/scrollToTop.js +++ b/libBrowser/tool/scrollToTop.js @@ -1,8 +1,9 @@ /** * 滚动到页面顶部 * @alias yd_browser_scrollToTop - * @author Zhoozie * @category browser + * @author Zhoozie + * @example */ export default () => { const height = document.documentElement.scrollTop || document.body.scrollTop; diff --git a/lib/browser/viewTransition.js b/libBrowser/tool/viewTransition.js similarity index 96% rename from lib/browser/viewTransition.js rename to libBrowser/tool/viewTransition.js index 96fe5cd..3fe1cd4 100644 --- a/lib/browser/viewTransition.js +++ b/libBrowser/tool/viewTransition.js @@ -1,10 +1,11 @@ /** * 应用 viewTransition api - * @author imddc https://github.com/imddc - * @category browser * @alias yd_browser_viewTransition + * @category browser * @param {any} fn 用于触发过渡的函数 + * @author imddc https://github.com/imddc * @summary 应用场景:使用viewTransition进行视图过渡 + * @example yd_browser_viewTransition() */ export default (fn) => { const isSupport = document !== undefined && 'startViewTransition' in document; diff --git a/libNode/crypto/_meta.json b/libNode/crypto/_meta.json index b69ab8a..075c801 100644 --- a/libNode/crypto/_meta.json +++ b/libNode/crypto/_meta.json @@ -1,4 +1,4 @@ { - "name": "加密", + "name": "crypto", "describe": "Node.js中可用的加密函数" } diff --git a/libNode/crypto/hmacMd5.js b/libNode/crypto/hmacMd5.js new file mode 100644 index 0000000..3177c5c --- /dev/null +++ b/libNode/crypto/hmacMd5.js @@ -0,0 +1,15 @@ +import { createHmac } from 'node:crypto'; +/** + * @alias yd_crypto_hmacMd5 + * @category crypto + * @param {string} data 加密数据 + * @param {string} key 加密密钥 + * @param {string} encoding 输出编码 + * @returns {string} 返回加密结果 + * @author 陈随易 + * @example yd_crypto_hmacMd5() + */ +export default (data, key, encoding = 'hex') => { + const result = createHmac('md5', key).update(data).digest(encoding); + return result; +}; diff --git a/libNode/crypto/md5.js b/libNode/crypto/md5.js new file mode 100644 index 0000000..eba7a44 --- /dev/null +++ b/libNode/crypto/md5.js @@ -0,0 +1,14 @@ +import { createHash } from 'node:crypto'; +/** + * @alias yd_crypto_md5 + * @category crypto + * @param {string} data 加密数据 + * @param {string} encoding 输出编码 + * @returns {string} 返回加密结果 + * @author 陈随易 + * @example yd_crypto_md5() + */ +export default (data, encoding = 'hex') => { + const result = createHash('md5').update(data).digest(encoding); + return result; +}; diff --git a/libPend/dataURLtoFile.test.js b/libPend/dataURLtoFile.test.js deleted file mode 100644 index 7ffe725..0000000 --- a/libPend/dataURLtoFile.test.js +++ /dev/null @@ -1,24 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_file_dataURLtoFile from '../lib/file/dataURLtoFile.js'; - -describe('yd_file_dataURLtoFile', () => { - it('将Base64 DataURL转换为文件对象', () => { - const dataurl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFt3Y6uAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+j8jJIAAAAKdJREFUOI3tk79Lw1AUx3+fP2lKgUGKwWCwQhNvYwJjIcMjRjJpVgQd5eQgPlIImZzGWaIqYw+VwZkZMb3M6e4vB7vPz9fXv3f3tLm7Y2Nj/8lY3ZmRjg2V8HJxn2ZsZfL6i9fXx+g/1C1Yi4eHJ7OZfYfI8lZsVtP0ZtP0pk4VYlP6AQLBAJwMjBW7Xf9a5Z/Zw0+4hDpUw1T4QeUdRcBlwR7rK9wRv8Dee4Z8mzZ7Kx1e0f9v7Mf7+JxT4Y9y9w7r8H+cJ7+fQV9sJfW9O+1oKv7j1i1cZJ7U2Lr2y+9vPv5G4z/9h8V3G8R3G8J3G7NzV6x/4EAAAAASUVORK5CYII='; - const filename = 'image.png'; - - const result = yd_file_dataURLtoFile(dataurl, filename); - - expect(result).toBeInstanceOf(File); - expect(result.name).toBe(filename); - expect(result.type).toBe('image/png'); - }); - - it('处理没有指定文件名的情况', () => { - const dataurl = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/4QA6RXhpZgAATU0AKgAAAAgAA1QAA'; - const result = yd_file_dataURLtoFile(dataurl); - - expect(result).toBeInstanceOf(File); - expect(result.name).toBe('filename'); - expect(result.type).toBe('image/jpeg'); - }); -}); diff --git a/libPend/denyChange.js b/libPend/denyChange.js deleted file mode 100644 index 5c0a794..0000000 --- a/libPend/denyChange.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * 浏览器禁止切换页面 - * @author Nil - * @category 浏览器 - * @alias yd_array_uniqWith - * @param {Function} 函数 - * @param {number} number 切换次数,默认是3次 - * @param {string} msg 切换次数,默认提示内容“切换次数超过限制” - * @summary 应用场景:线上考试场景 - */ - -export default (number, msg) => { - window.onblur = function () { - let i = number || 3; - i--; - if (i == 0) { - const res = msg || '切换次数超过限制'; - alert(res); - } - }; - return window.onblur; -}; diff --git a/libPend/download.js b/libPend/download.js deleted file mode 100644 index d06541a..0000000 --- a/libPend/download.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * 将字符串、画布元素、图像元素、`Blob`或`File`、`ArrayBuffer`或类型化数组、对象(转为JSON字符串)等下载为文件 - * @param {HTMLCanvasElement | HTMLMediaElement | HTMLImageElement | HTMLSourceElement | HTMLTrackElement | HTMLEmbedElement | HTMLObjectElement | File | Blob | ArrayBuffer | URL | string} content 下载内容/下载链接 - * @param {string} [filename] 文件名 默认使用页面标题 - * @param {boolean} [isURL] 传入的字符串是否为下载链接。(否则将作为文本内容下载) 默认为`false` - */ -export default (content, filename = document.title, isURL) => { - if (content === void 0 || content === null) throw new TypeError('无下载内容!'); - const anchor = document.createElement('a'); - // 将数值类型与布尔类型转为字符串 - if (typeof content === 'number' || typeof content === 'bigint' || typeof content === 'boolean') return yd_download(String(content), filename); - if (typeof content === 'string') { - if (isURL) anchor.href = content; - // 下载为文本内容 - else return yd_download(new Blob([content]), filename); - } - // 对象类型 - else if (typeof content === 'object') { - // 画布元素转为base64作为下载链接 - if (content instanceof HTMLCanvasElement) { - anchor.href = content.toDataURL('image/png'); - } - // 包含src属性的元素直接使用src属性作为下载链接 - else if (content instanceof HTMLImageElement || content instanceof HTMLMediaElement || content instanceof HTMLSourceElement || content instanceof HTMLTrackElement || content instanceof HTMLEmbedElement) { - anchor.href = content.src; - } - // object元素使用data属性作为下载链接 - else if (content instanceof HTMLObjectElement) { - anchor.href = content.data; - } - // File和Blob类型转为url作为下载链接 - else if (content instanceof Blob) { - anchor.href = URL.createObjectURL(content); - } - // ArrayBuffer将转为Blob进行下载 - else if (content instanceof ArrayBuffer) { - return yd_download(new Blob([content]), filename); - } - // URL对象转为字符串形式 - else if (content instanceof URL) { - anchor.href = content.href; - } - // 类型化数组与DataView 将转为ArrayBuffer - else if (ArrayBuffer.isView(content)) { - return yd_download(content.buffer, filename); - } else { - // 尝试转为JSON字符串 - try { - return yd_download(new Blob([JSON.stringify(content)]), filename); - } catch { - throw new TypeError('对象可能包含循环引用。'); - } - } - } else { - throw new TypeError('无法处理的类型'); - } - // 设置文件名 - anchor.download = filename; - anchor.click(); -}; diff --git a/libPend/fileInfo.test.js b/libPend/fileInfo.test.js deleted file mode 100644 index 0b70d05..0000000 --- a/libPend/fileInfo.test.js +++ /dev/null @@ -1,37 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_file_fileInfo from '../lib/file/fileInfo.js'; - -describe('yd_file_fileInfo', () => { - it('解析文件路径信息', () => { - const path = '/path/to/file.txt'; - const result = yd_file_fileInfo(path); - - expect(result).toEqual({ - name: 'file', - type: 'txt', - fullName: 'file.txt' - }); - }); - - it('处理没有文件名的路径', () => { - const path = '/path/to/'; - const result = yd_file_fileInfo(path); - - expect(result).toEqual({ - name: '', - type: '', - fullName: '' - }); - }); - - it('处理文件名中包含多个"."的情况', () => { - const path = '/path/to/file.name.txt'; - const result = yd_file_fileInfo(path); - - expect(result).toEqual({ - name: 'file.name', - type: 'txt', - fullName: 'file.name.txt' - }); - }); -}); diff --git a/libPend/fileToDataURL.test.js b/libPend/fileToDataURL.test.js deleted file mode 100644 index cb5be38..0000000 --- a/libPend/fileToDataURL.test.js +++ /dev/null @@ -1,13 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import yd_file_fileToDataURL from '../lib/file/fileToDataURL.js'; - -describe('yd_file_fileToDataURL', () => { - it('将文件转换为base64字符串', () => { - // 模拟一个文件对象 - const file = new File(['Hello, World!'], 'test.txt', { type: 'text/plain' }); - // 调用文件转换为base64的函数 - yd_file_fileToDataURL(file, function (base64String) { - expect(base64String).not.toBe(''); - }); - }); -}); diff --git a/libPend/hashCode.js b/libPend/hashCode.js deleted file mode 100644 index 9a30ed4..0000000 --- a/libPend/hashCode.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * 哈希生成 - * @author bai.zixv - * @category 加解密 - * @param {string} str 字符串 - * @returns {number} 哈希值 - */ -export default (str) => { - let hash = 0; - for (let i = 0; i < str.length; i++) { - const char = str.charCodeAt(i); - hash = (hash << 5) - hash + char; - hash |= 0; - } - return hash; -}; diff --git a/libPend/replaceApi.js b/libPend/replaceApi.js deleted file mode 100644 index 08c3311..0000000 --- a/libPend/replaceApi.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * - * @author alvis - * @category 帮助 - * @param {String} url 网络请求地址 - * @param {...any} agrs - * @returns {String} 替换后的url - * @description 替换url中的占位符 /api/project/data-image/app/{projectId} => /api/project/data-image/app/123 - */ -export default (url, ...agrs) => { - let index = 0; - return url.replace(/{(.*?)}/g, (match) => { - match = agrs[index]; - index++; - return match; - }); -}; diff --git a/libPend/serialize.js b/libPend/serialize.js deleted file mode 100644 index 34e726c..0000000 --- a/libPend/serialize.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * 序列化对象 - * @author bai.zixv - * @category 对象 - * @param {Object} obj 对象 - * @returns {string} 返回对应的序列化值 - */ -export default (obj) => { - if (typeof obj !== 'object' || obj === null) { - return String(obj); - } - const keys = Object.keys(obj).sort(); - const result = keys.map((key) => `${key}:${yd_object_serialize(obj[key])}`).join('|'); - return `{${result}}`; -}; diff --git a/libPend/sortBy.js b/libPend/sortBy.js deleted file mode 100644 index c681107..0000000 --- a/libPend/sortBy.js +++ /dev/null @@ -1,123 +0,0 @@ -// >>> HELPERS <<< - -const castComparer = (comparer) => (a, b, order) => comparer(a, b, order) * order; - -const unpackObjectSorter = function (sortByObj) { - const { asc, desc } = sortByObj || {}; - const order = asc ? 1 : -1; - const sortBy = asc || desc; - - const comparer = sortByObj.comparer && castComparer(sortByObj.comparer); - - return { order, sortBy, comparer }; -}; - -// >>> SORTERS <<< - -const multiPropertySorterProvider = function (defaultComparer) { - return function multiPropertySorter(sortBy, sortByArr, depth, order, comparer, a, b) { - let valA; - let valB; - - if (typeof sortBy === 'string') { - valA = a[sortBy]; - valB = b[sortBy]; - } else if (typeof sortBy === 'function') { - valA = sortBy(a); - valB = sortBy(b); - } else { - const objectSorterConfig = unpackObjectSorter(sortBy); - return multiPropertySorter(objectSorterConfig.sortBy, sortByArr, depth, objectSorterConfig.order, objectSorterConfig.comparer || defaultComparer, a, b); - } - - const equality = comparer(valA, valB, order); - - if ((equality === 0 || (valA == null && valB == null)) && sortByArr.length > depth) { - return multiPropertySorter(sortByArr[depth], sortByArr, depth + 1, order, comparer, a, b); - } - - return equality; - }; -}; - -function getSortStrategy(sortBy, comparer, order) { - // Flat array sorter - if (sortBy === undefined || sortBy === true) { - return (a, b) => comparer(a, b, order); - } - - // Sort list of objects by single object key - if (typeof sortBy === 'string') { - return (a, b) => comparer(a[sortBy], b[sortBy], order); - } - - // Sort list of objects by single function sorter - if (typeof sortBy === 'function') { - return (a, b) => comparer(sortBy(a), sortBy(b), order); - } - - // Sort by multiple properties - if (Array.isArray(sortBy)) { - const multiPropSorter = multiPropertySorterProvider(comparer); - return (a, b) => multiPropSorter(sortBy[0], sortBy, 1, order, comparer, a, b); - } - - // Unpack object config to get actual sorter strategy - const objectSorterConfig = unpackObjectSorter(sortBy); - return getSortStrategy(objectSorterConfig.sortBy, objectSorterConfig.comparer || comparer, objectSorterConfig.order); -} - -const sortArray = function (order, ctx, sortBy, comparer) { - if (!Array.isArray(ctx)) { - return ctx; - } - - // Unwrap sortBy if array with only 1 value to get faster sort strategy - if (Array.isArray(sortBy) && sortBy.length < 2) { - [sortBy] = sortBy; - } - - return ctx.sort(getSortStrategy(sortBy, comparer, order)); -}; - -// >>> Public <<< - -function createNewSortInstance(opts) { - const comparer = castComparer(opts.comparer); - - return function (arrayToSort) { - return { - asc(sortBy) { - return sortArray(1, arrayToSort.slice(), sortBy, comparer); - }, - desc(sortBy) { - return sortArray(-1, arrayToSort.slice(), sortBy, comparer); - }, - by(sortBy) { - return sortArray(1, arrayToSort.slice(), sortBy, comparer); - } - }; - }; -} - -function defaultComparer(a, b, order) { - if (a == null) return order; - if (b == null) return -order; - - if (typeof a !== typeof b) { - if (typeof a < typeof b) { - return -1; - } else { - return 1; - } - } - - if (a < b) return -1; - if (a > b) return 1; - - return 0; -} - -export default createNewSortInstance({ - comparer: defaultComparer -}); diff --git a/libPend/uniqueByFields.js b/libPend/uniqueByFields.js deleted file mode 100644 index 4f8c555..0000000 --- a/libPend/uniqueByFields.js +++ /dev/null @@ -1,26 +0,0 @@ -import { yd_hash_getHashCode } from './yd_hash_getHashCode'; -import { yd_object_serialize } from '../object/yd_object_serialize'; -/** - * 数组去重 - * @author bai.zixv - * @category 数组 - * @param {Array} array 对象数组数据 比如, [{id: 1, name: "a"}, {id: 2, name: "b"}, {id: 1, name: "a"}] - * @param {Array} fields 对象数组子元素对象的字段数组, 比如: ['id', 'name'] - * @returns {Array} 返回去重后的对象数组 - */ -export default (array, fields) => { - const uniqueMap = new Map(); - - const resultArray = array.filter((item) => { - const uniqueKey = fields.map((field) => (typeof item[field] === 'object' ? yd_hash_getHashCode(yd_object_serialize(item[field])) : item[field])).join('|'); - - if (uniqueMap.has(uniqueKey)) { - return false; - } else { - uniqueMap.set(uniqueKey, true); - return true; - } - }); - - return resultArray; -}; diff --git a/package.json b/package.json index f0dd94d..c226036 100644 --- a/package.json +++ b/package.json @@ -56,30 +56,31 @@ "inspect": "eslint --inspect-config" }, "dependencies": { - "date-fns": "^3.6.0", - "nanoid": "^5.0.7" + "date-fns": "^4.0.0", + "es-toolkit": "^1.19.0", + "lodash-es": "^4.17.21" }, "devDependencies": { "@eslint/config-inspector": "^0.5.4", - "@eslint/js": "^9.9.1", - "@vitest/ui": "^2.0.5", + "@eslint/js": "^9.10.0", + "@vitest/ui": "^2.1.1", "colorette": "^2.0.20", "del-cli": "^5.1.0", "docdash-extended-chensuiyi": "^1.1.1", - "eslint": "^9.9.1", + "eslint": "^9.10.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jsdoc": "^50.2.2", + "eslint-plugin-jsdoc": "^50.2.3", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-regexp": "^2.6.0", "fs-extra": "^11.2.0", "globals": "^15.9.0", - "happy-dom": "^15.0.0", + "happy-dom": "^15.7.4", "jsdoc": "^4.0.3", - "lint-staged": "^15.2.9", + "lint-staged": "^15.2.10", "log-symbols": "^7.0.0", "prettier": "^3.3.3", "simple-git-hooks": "^2.11.1", - "vitest": "^2.0.5" + "vitest": "^2.1.1" }, "simple-git-hooks": { "pre-commit": "pnpm exec lint-staged" diff --git a/vitest.config.mjs b/vitest.config.mjs index 9663af0..9ef0ace 100644 --- a/vitest.config.mjs +++ b/vitest.config.mjs @@ -3,6 +3,7 @@ import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { globals: true, - dir: './lib' + // include: ['**/lib/*.test.js'], + dir: './' } });