@cloudcome/utils-core 1.14.0 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dict.cjs.map +1 -1
- package/dist/dict.d.ts +1 -0
- package/dist/dict.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/number.d.ts +4 -4
- package/dist/string2.cjs.map +1 -1
- package/dist/string2.mjs.map +1 -1
- package/package.json +1 -1
package/dist/dict.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dict.cjs","sources":["../src/dict.ts"],"sourcesContent":["import type { AnyObject, MergeIntersection, UnionToIntersection, UnionToTuple } from './types';\n\nexport type DictKey = string;\nexport type DictValue = number | string;\nexport type DictMetaAppend = {\n key?: string;\n value?: string | number;\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n [key: string]: any;\n};\nexport type DictMeta<A extends DictMetaAppend> = A & {\n value: DictValue;\n};\nexport type DictDescription<A extends DictMetaAppend> = Record<DictKey, DictMeta<A>>;\n\nconst dictError = Symbol('dictKeyError');\n\ntype _StartWithDollarSign<T extends string> = T extends `$${infer R}` ? R : never;\n\ntype _CheckDefinition<O extends AnyObject> = {\n // [K in keyof O & string]: K extends Capitalize<K> ? O[K] : `错误:枚举键名 ${K} 必须大写字母开头`;\n [K in keyof O & string]: K extends Capitalize<K>\n ? K extends `$${infer R}`\n ? O[K] & { [dictError]: `错误:枚举键名 ${K} 不能以 $ 符号开头` }\n : O[K]\n : O[K] & { [dictError]: `错误:枚举键名 ${K} 必须以大写字母开头` };\n};\n\ntype _ToOriginDefProp<T extends AnyObject> = {\n [K in keyof T as `$${K & string}`]: MergeIntersection<T[K] & { readonly key: K }>;\n};\n\ntype _KVRecord<T> = T extends Record<string, AnyObject>\n ? {\n readonly [K in keyof T]: T[K]['value'];\n }\n : never;\n\ntype _VKRecord<T> = T extends Record<string, AnyObject>\n ? MergeIntersection<\n UnionToIntersection<\n {\n [K in keyof T]: {\n [P in keyof T[K] as P extends 'value' ? T[K][P] & (string | number) : never]: K;\n };\n }[keyof T]\n >\n >\n : never;\n\nexport type DictExpose<A extends DictMetaAppend, E extends DictDescription<A>> = _ToOriginDefProp<E> &\n _KVRecord<E> & {\n readonly definition: E;\n readonly descriptions: MergeIntersection<A & { key: keyof E }>[];\n readonly keys: UnionToTuple<keyof E>;\n readonly length: UnionToTuple<keyof E>['length'];\n readonly values: UnionToTuple<E[keyof E]['value']>;\n readonly kvRecord: _KVRecord<E>;\n readonly vkRecord: _VKRecord<E>;\n toKeyRecord: <P extends keyof A>(prop: P) => Record<keyof E, A[P]>;\n toValRecord: <P extends keyof A>(prop: P) => Record<E[keyof E]['value'], A[P]>;\n };\n\n/**\n * 定义一个枚举类型,如果需要类型提示,需要使用 declareDict 函数定义枚举。\n * @template A - 枚举元数据附加类型,扩展自 DictMetaAppend\n * @template E - 枚举描述类型,键为枚举键名,值为枚举元数据\n * @param {_CheckDefinition<E>} definition - 枚举定义对象\n * @returns {DictExpose<A, E>} 返回枚举的完整暴露对象\n * @example\n * ```typescript\n * const Status = defineDict({\n * Pending: { value: 0, label: '待处理' },\n * Approved: { value: 1, label: '已批准' }\n * });\n * ```\n *\n * @property {E} definition - 原始枚举定义对象\n * @property {Array<MergeIntersection<A & { key: keyof E }>>} descriptions - 枚举项的完整描述数组\n * @property {UnionToTuple<keyof E>} keys - 枚举键名的元组\n * @property {\"UnionToTuple<keyof E>[\\\"length\\\"]\"} length - 枚举项的数量\n * @property {UnionToTuple<E[keyof E][\"value\"]>} values - 枚举值的元组\n * @property {Record<keyof E, E[keyof E][\"value\"]>} kvRecord - 键到值的映射记录\n * @property {Record<E[keyof E][\"value\"], E[keyof E]>} vkRecord - 值到键的映射记录\n * @property {function} toKeyRecord - 根据属性名创建键到属性值的映射记录\n * @property {function} toValueRecord - 根据属性名创建值到属性值的映射记录\n */\nfunction _defineDict<A extends DictMetaAppend, const E extends DictDescription<A>>(\n definition: _CheckDefinition<E>,\n): DictExpose<A, E> {\n const keys = Object.keys(definition);\n\n return {\n ...[...Object.entries(definition)].reduce((acc, [key, dfn]) => {\n if (key[0].toUpperCase() !== key[0]) {\n throw new Error(`错误:枚举键名 ${key} 必须以大写字母开头`);\n }\n\n if (key.startsWith('$')) {\n throw new Error(`错误:枚举键名 ${key} 不能以 $ 符号开头`);\n }\n\n // @ts-ignore\n acc[key] = dfn.value;\n // @ts-ignore\n acc[`$${key}`] = { key, ...dfn };\n return acc;\n }, {}),\n definition,\n descriptions: keys.map((key) => ({\n key,\n ...definition[key],\n })),\n keys,\n length: keys.length,\n values: keys.map((key) => definition[key as keyof E].value),\n kvRecord: keys.reduce((acc, key) => {\n // @ts-ignore\n acc[key] = definition[key].value;\n return acc;\n }, {}),\n vkRecord: keys.reduce((acc, key) => {\n // @ts-ignore\n acc[definition[key].value] = key;\n return acc;\n }, {}),\n toKeyRecord<P extends keyof A>(prop: P) {\n return keys.reduce((acc, key) => {\n // @ts-ignore\n acc[key] = definition[key][prop];\n return acc;\n }, {});\n },\n toValRecord<P extends keyof A>(prop: P) {\n return keys.reduce(\n (acc, key) => {\n // @ts-ignore\n acc[definition[key].value] = definition[key][prop];\n return acc;\n },\n {} as Record<E[keyof E]['value'], A[P]>,\n );\n },\n } as unknown as DictExpose<A, E>;\n}\n\n/**\n * 声明一个枚举工厂函数\n * @template A - 枚举元数据附加类型,扩展自 DictMetaAppend\n * @returns {Object} 返回包含 define 方法的对象\n *\n * @property {function} define - 定义枚举的函数\n * @template E - 枚举描述类型\n * @param {_CheckDefinition<E>} definition - 枚举定义对象\n * @returns {DictExpose<A, E>} 返回枚举的完整暴露对象\n * @example\n * ```typescript\n * const createStatusDict = declareDict<{ label: string }>();\n * const Status = createStatusDict.define({\n * Pending: { value: 0, label: '待处理' },\n * Approved: { value: 1, label: '已批准' }\n * });\n * ```\n */\nexport function declareDict<A extends DictMetaAppend>() {\n return {\n define<const E extends DictDescription<A>>(definition: _CheckDefinition<E>): DictExpose<A, E> {\n return _defineDict(definition);\n },\n };\n}\n"],"names":[],"mappings":";;AAuFA,SAAS,YACP,YACkB;AACZ,QAAA,OAAO,OAAO,KAAK,UAAU;AAE5B,SAAA;AAAA,IACL,GAAG,CAAC,GAAG,OAAO,QAAQ,UAAU,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM;AAC7D,UAAI,IAAI,CAAC,EAAE,kBAAkB,IAAI,CAAC,GAAG;AACnC,cAAM,IAAI,MAAM,WAAW,GAAG,YAAY;AAAA,MAAA;AAGxC,UAAA,IAAI,WAAW,GAAG,GAAG;AACvB,cAAM,IAAI,MAAM,WAAW,GAAG,aAAa;AAAA,MAAA;AAIzC,UAAA,GAAG,IAAI,IAAI;AAEf,UAAI,IAAI,GAAG,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI;AACxB,aAAA;AAAA,IACT,GAAG,EAAE;AAAA,IACL;AAAA,IACA,cAAc,KAAK,IAAI,CAAC,SAAS;AAAA,MAC/B;AAAA,MACA,GAAG,WAAW,GAAG;AAAA,IAAA,EACjB;AAAA,IACF;AAAA,IACA,QAAQ,KAAK;AAAA,IACb,QAAQ,KAAK,IAAI,CAAC,QAAQ,WAAW,GAAc,EAAE,KAAK;AAAA,IAC1D,UAAU,KAAK,OAAO,CAAC,KAAK,QAAQ;AAElC,UAAI,GAAG,IAAI,WAAW,GAAG,EAAE;AACpB,aAAA;AAAA,IACT,GAAG,EAAE;AAAA,IACL,UAAU,KAAK,OAAO,CAAC,KAAK,QAAQ;AAElC,UAAI,WAAW,GAAG,EAAE,KAAK,IAAI;AACtB,aAAA;AAAA,IACT,GAAG,EAAE;AAAA,IACL,YAA+B,MAAS;AACtC,aAAO,KAAK,OAAO,CAAC,KAAK,QAAQ;AAE/B,YAAI,GAAG,IAAI,WAAW,GAAG,EAAE,IAAI;AACxB,eAAA;AAAA,MACT,GAAG,EAAE;AAAA,IACP;AAAA,IACA,YAA+B,MAAS;AACtC,aAAO,KAAK;AAAA,QACV,CAAC,KAAK,QAAQ;AAER,cAAA,WAAW,GAAG,EAAE,KAAK,IAAI,WAAW,GAAG,EAAE,IAAI;AAC1C,iBAAA;AAAA,QACT;AAAA,QACA,CAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAEJ;AACF;AAoBO,SAAS,cAAwC;AAC/C,SAAA;AAAA,IACL,OAA2C,YAAmD;AAC5F,aAAO,YAAY,UAAU;AAAA,IAAA;AAAA,EAEjC;AACF;;"}
|
|
1
|
+
{"version":3,"file":"dict.cjs","sources":["../src/dict.ts"],"sourcesContent":["import type { AnyObject, MergeIntersection, UnionToIntersection, UnionToTuple } from './types';\n\nexport type DictKey = string;\nexport type DictValue = number | string;\nexport type DictMetaAppend = {\n key?: string;\n value?: string | number;\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n [key: string]: any;\n};\nexport type DictMeta<A extends DictMetaAppend> = A & {\n value: DictValue;\n};\nexport type DictDescription<A extends DictMetaAppend> = Record<DictKey, DictMeta<A>>;\n\nconst dictError = Symbol('dictKeyError');\n\ntype _StartWithDollarSign<T extends string> = T extends `$${infer R}` ? R : never;\n\ntype _CheckDefinition<O extends AnyObject> = {\n // [K in keyof O & string]: K extends Capitalize<K> ? O[K] : `错误:枚举键名 ${K} 必须大写字母开头`;\n [K in keyof O & string]: K extends Capitalize<K>\n ? K extends `$${infer R}`\n ? O[K] & { [dictError]: `错误:枚举键名 ${K} 不能以 $ 符号开头` }\n : O[K]\n : O[K] & { [dictError]: `错误:枚举键名 ${K} 必须以大写字母开头` };\n};\n\ntype _ToOriginDefProp<T extends AnyObject> = {\n [K in keyof T as `$${K & string}`]: MergeIntersection<T[K] & { readonly key: K }>;\n};\n\ntype _KVRecord<T> = T extends Record<string, AnyObject>\n ? {\n readonly [K in keyof T]: T[K]['value'];\n }\n : never;\n\ntype _VKRecord<T> = T extends Record<string, AnyObject>\n ? MergeIntersection<\n UnionToIntersection<\n {\n [K in keyof T]: {\n [P in keyof T[K] as P extends 'value' ? T[K][P] & (string | number) : never]: K;\n };\n }[keyof T]\n >\n >\n : never;\n\nexport type DictExpose<A extends DictMetaAppend, E extends DictDescription<A>> = _ToOriginDefProp<E> &\n _KVRecord<E> & {\n readonly definition: E;\n readonly descriptions: MergeIntersection<A & { key: keyof E; value: E[keyof E]['value'] }>[];\n readonly keys: UnionToTuple<keyof E>;\n readonly length: UnionToTuple<keyof E>['length'];\n readonly values: UnionToTuple<E[keyof E]['value']>;\n readonly kvRecord: _KVRecord<E>;\n readonly vkRecord: _VKRecord<E>;\n toKeyRecord: <P extends keyof A>(prop: P) => Record<keyof E, A[P]>;\n toValRecord: <P extends keyof A>(prop: P) => Record<E[keyof E]['value'], A[P]>;\n };\n\n/**\n * 定义一个枚举类型,如果需要类型提示,需要使用 declareDict 函数定义枚举。\n * @template A - 枚举元数据附加类型,扩展自 DictMetaAppend\n * @template E - 枚举描述类型,键为枚举键名,值为枚举元数据\n * @param {_CheckDefinition<E>} definition - 枚举定义对象\n * @returns {DictExpose<A, E>} 返回枚举的完整暴露对象\n * @example\n * ```typescript\n * const Status = defineDict({\n * Pending: { value: 0, label: '待处理' },\n * Approved: { value: 1, label: '已批准' }\n * });\n * ```\n *\n * @property {E} definition - 原始枚举定义对象\n * @property {Array<MergeIntersection<A & { key: keyof E }>>} descriptions - 枚举项的完整描述数组\n * @property {UnionToTuple<keyof E>} keys - 枚举键名的元组\n * @property {\"UnionToTuple<keyof E>[\\\"length\\\"]\"} length - 枚举项的数量\n * @property {UnionToTuple<E[keyof E][\"value\"]>} values - 枚举值的元组\n * @property {Record<keyof E, E[keyof E][\"value\"]>} kvRecord - 键到值的映射记录\n * @property {Record<E[keyof E][\"value\"], E[keyof E]>} vkRecord - 值到键的映射记录\n * @property {function} toKeyRecord - 根据属性名创建键到属性值的映射记录\n * @property {function} toValueRecord - 根据属性名创建值到属性值的映射记录\n */\nfunction _defineDict<A extends DictMetaAppend, const E extends DictDescription<A>>(\n definition: _CheckDefinition<E>,\n): DictExpose<A, E> {\n const keys = Object.keys(definition);\n\n return {\n ...[...Object.entries(definition)].reduce((acc, [key, dfn]) => {\n if (key[0].toUpperCase() !== key[0]) {\n throw new Error(`错误:枚举键名 ${key} 必须以大写字母开头`);\n }\n\n if (key.startsWith('$')) {\n throw new Error(`错误:枚举键名 ${key} 不能以 $ 符号开头`);\n }\n\n // @ts-ignore\n acc[key] = dfn.value;\n // @ts-ignore\n acc[`$${key}`] = { key, ...dfn };\n return acc;\n }, {}),\n definition,\n descriptions: keys.map((key) => ({\n key,\n ...definition[key],\n })),\n keys,\n length: keys.length,\n values: keys.map((key) => definition[key as keyof E].value),\n kvRecord: keys.reduce((acc, key) => {\n // @ts-ignore\n acc[key] = definition[key].value;\n return acc;\n }, {}),\n vkRecord: keys.reduce((acc, key) => {\n // @ts-ignore\n acc[definition[key].value] = key;\n return acc;\n }, {}),\n toKeyRecord<P extends keyof A>(prop: P) {\n return keys.reduce((acc, key) => {\n // @ts-ignore\n acc[key] = definition[key][prop];\n return acc;\n }, {});\n },\n toValRecord<P extends keyof A>(prop: P) {\n return keys.reduce(\n (acc, key) => {\n // @ts-ignore\n acc[definition[key].value] = definition[key][prop];\n return acc;\n },\n {} as Record<E[keyof E]['value'], A[P]>,\n );\n },\n } as unknown as DictExpose<A, E>;\n}\n\n/**\n * 声明一个枚举工厂函数\n * @template A - 枚举元数据附加类型,扩展自 DictMetaAppend\n * @returns {Object} 返回包含 define 方法的对象\n *\n * @property {function} define - 定义枚举的函数\n * @template E - 枚举描述类型\n * @param {_CheckDefinition<E>} definition - 枚举定义对象\n * @returns {DictExpose<A, E>} 返回枚举的完整暴露对象\n * @example\n * ```typescript\n * const createStatusDict = declareDict<{ label: string }>();\n * const Status = createStatusDict.define({\n * Pending: { value: 0, label: '待处理' },\n * Approved: { value: 1, label: '已批准' }\n * });\n * ```\n */\nexport function declareDict<A extends DictMetaAppend>() {\n return {\n define<const E extends DictDescription<A>>(definition: _CheckDefinition<E>): DictExpose<A, E> {\n return _defineDict(definition);\n },\n };\n}\n"],"names":[],"mappings":";;AAuFA,SAAS,YACP,YACkB;AACZ,QAAA,OAAO,OAAO,KAAK,UAAU;AAE5B,SAAA;AAAA,IACL,GAAG,CAAC,GAAG,OAAO,QAAQ,UAAU,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM;AAC7D,UAAI,IAAI,CAAC,EAAE,kBAAkB,IAAI,CAAC,GAAG;AACnC,cAAM,IAAI,MAAM,WAAW,GAAG,YAAY;AAAA,MAAA;AAGxC,UAAA,IAAI,WAAW,GAAG,GAAG;AACvB,cAAM,IAAI,MAAM,WAAW,GAAG,aAAa;AAAA,MAAA;AAIzC,UAAA,GAAG,IAAI,IAAI;AAEf,UAAI,IAAI,GAAG,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI;AACxB,aAAA;AAAA,IACT,GAAG,EAAE;AAAA,IACL;AAAA,IACA,cAAc,KAAK,IAAI,CAAC,SAAS;AAAA,MAC/B;AAAA,MACA,GAAG,WAAW,GAAG;AAAA,IAAA,EACjB;AAAA,IACF;AAAA,IACA,QAAQ,KAAK;AAAA,IACb,QAAQ,KAAK,IAAI,CAAC,QAAQ,WAAW,GAAc,EAAE,KAAK;AAAA,IAC1D,UAAU,KAAK,OAAO,CAAC,KAAK,QAAQ;AAElC,UAAI,GAAG,IAAI,WAAW,GAAG,EAAE;AACpB,aAAA;AAAA,IACT,GAAG,EAAE;AAAA,IACL,UAAU,KAAK,OAAO,CAAC,KAAK,QAAQ;AAElC,UAAI,WAAW,GAAG,EAAE,KAAK,IAAI;AACtB,aAAA;AAAA,IACT,GAAG,EAAE;AAAA,IACL,YAA+B,MAAS;AACtC,aAAO,KAAK,OAAO,CAAC,KAAK,QAAQ;AAE/B,YAAI,GAAG,IAAI,WAAW,GAAG,EAAE,IAAI;AACxB,eAAA;AAAA,MACT,GAAG,EAAE;AAAA,IACP;AAAA,IACA,YAA+B,MAAS;AACtC,aAAO,KAAK;AAAA,QACV,CAAC,KAAK,QAAQ;AAER,cAAA,WAAW,GAAG,EAAE,KAAK,IAAI,WAAW,GAAG,EAAE,IAAI;AAC1C,iBAAA;AAAA,QACT;AAAA,QACA,CAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAEJ;AACF;AAoBO,SAAS,cAAwC;AAC/C,SAAA;AAAA,IACL,OAA2C,YAAmD;AAC5F,aAAO,YAAY,UAAU;AAAA,IAAA;AAAA,EAEjC;AACF;;"}
|
package/dist/dict.d.ts
CHANGED
|
@@ -35,6 +35,7 @@ export type DictExpose<A extends DictMetaAppend, E extends DictDescription<A>> =
|
|
|
35
35
|
readonly definition: E;
|
|
36
36
|
readonly descriptions: MergeIntersection<A & {
|
|
37
37
|
key: keyof E;
|
|
38
|
+
value: E[keyof E]['value'];
|
|
38
39
|
}>[];
|
|
39
40
|
readonly keys: UnionToTuple<keyof E>;
|
|
40
41
|
readonly length: UnionToTuple<keyof E>['length'];
|
package/dist/dict.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dict.mjs","sources":["../src/dict.ts"],"sourcesContent":["import type { AnyObject, MergeIntersection, UnionToIntersection, UnionToTuple } from './types';\n\nexport type DictKey = string;\nexport type DictValue = number | string;\nexport type DictMetaAppend = {\n key?: string;\n value?: string | number;\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n [key: string]: any;\n};\nexport type DictMeta<A extends DictMetaAppend> = A & {\n value: DictValue;\n};\nexport type DictDescription<A extends DictMetaAppend> = Record<DictKey, DictMeta<A>>;\n\nconst dictError = Symbol('dictKeyError');\n\ntype _StartWithDollarSign<T extends string> = T extends `$${infer R}` ? R : never;\n\ntype _CheckDefinition<O extends AnyObject> = {\n // [K in keyof O & string]: K extends Capitalize<K> ? O[K] : `错误:枚举键名 ${K} 必须大写字母开头`;\n [K in keyof O & string]: K extends Capitalize<K>\n ? K extends `$${infer R}`\n ? O[K] & { [dictError]: `错误:枚举键名 ${K} 不能以 $ 符号开头` }\n : O[K]\n : O[K] & { [dictError]: `错误:枚举键名 ${K} 必须以大写字母开头` };\n};\n\ntype _ToOriginDefProp<T extends AnyObject> = {\n [K in keyof T as `$${K & string}`]: MergeIntersection<T[K] & { readonly key: K }>;\n};\n\ntype _KVRecord<T> = T extends Record<string, AnyObject>\n ? {\n readonly [K in keyof T]: T[K]['value'];\n }\n : never;\n\ntype _VKRecord<T> = T extends Record<string, AnyObject>\n ? MergeIntersection<\n UnionToIntersection<\n {\n [K in keyof T]: {\n [P in keyof T[K] as P extends 'value' ? T[K][P] & (string | number) : never]: K;\n };\n }[keyof T]\n >\n >\n : never;\n\nexport type DictExpose<A extends DictMetaAppend, E extends DictDescription<A>> = _ToOriginDefProp<E> &\n _KVRecord<E> & {\n readonly definition: E;\n readonly descriptions: MergeIntersection<A & { key: keyof E }>[];\n readonly keys: UnionToTuple<keyof E>;\n readonly length: UnionToTuple<keyof E>['length'];\n readonly values: UnionToTuple<E[keyof E]['value']>;\n readonly kvRecord: _KVRecord<E>;\n readonly vkRecord: _VKRecord<E>;\n toKeyRecord: <P extends keyof A>(prop: P) => Record<keyof E, A[P]>;\n toValRecord: <P extends keyof A>(prop: P) => Record<E[keyof E]['value'], A[P]>;\n };\n\n/**\n * 定义一个枚举类型,如果需要类型提示,需要使用 declareDict 函数定义枚举。\n * @template A - 枚举元数据附加类型,扩展自 DictMetaAppend\n * @template E - 枚举描述类型,键为枚举键名,值为枚举元数据\n * @param {_CheckDefinition<E>} definition - 枚举定义对象\n * @returns {DictExpose<A, E>} 返回枚举的完整暴露对象\n * @example\n * ```typescript\n * const Status = defineDict({\n * Pending: { value: 0, label: '待处理' },\n * Approved: { value: 1, label: '已批准' }\n * });\n * ```\n *\n * @property {E} definition - 原始枚举定义对象\n * @property {Array<MergeIntersection<A & { key: keyof E }>>} descriptions - 枚举项的完整描述数组\n * @property {UnionToTuple<keyof E>} keys - 枚举键名的元组\n * @property {\"UnionToTuple<keyof E>[\\\"length\\\"]\"} length - 枚举项的数量\n * @property {UnionToTuple<E[keyof E][\"value\"]>} values - 枚举值的元组\n * @property {Record<keyof E, E[keyof E][\"value\"]>} kvRecord - 键到值的映射记录\n * @property {Record<E[keyof E][\"value\"], E[keyof E]>} vkRecord - 值到键的映射记录\n * @property {function} toKeyRecord - 根据属性名创建键到属性值的映射记录\n * @property {function} toValueRecord - 根据属性名创建值到属性值的映射记录\n */\nfunction _defineDict<A extends DictMetaAppend, const E extends DictDescription<A>>(\n definition: _CheckDefinition<E>,\n): DictExpose<A, E> {\n const keys = Object.keys(definition);\n\n return {\n ...[...Object.entries(definition)].reduce((acc, [key, dfn]) => {\n if (key[0].toUpperCase() !== key[0]) {\n throw new Error(`错误:枚举键名 ${key} 必须以大写字母开头`);\n }\n\n if (key.startsWith('$')) {\n throw new Error(`错误:枚举键名 ${key} 不能以 $ 符号开头`);\n }\n\n // @ts-ignore\n acc[key] = dfn.value;\n // @ts-ignore\n acc[`$${key}`] = { key, ...dfn };\n return acc;\n }, {}),\n definition,\n descriptions: keys.map((key) => ({\n key,\n ...definition[key],\n })),\n keys,\n length: keys.length,\n values: keys.map((key) => definition[key as keyof E].value),\n kvRecord: keys.reduce((acc, key) => {\n // @ts-ignore\n acc[key] = definition[key].value;\n return acc;\n }, {}),\n vkRecord: keys.reduce((acc, key) => {\n // @ts-ignore\n acc[definition[key].value] = key;\n return acc;\n }, {}),\n toKeyRecord<P extends keyof A>(prop: P) {\n return keys.reduce((acc, key) => {\n // @ts-ignore\n acc[key] = definition[key][prop];\n return acc;\n }, {});\n },\n toValRecord<P extends keyof A>(prop: P) {\n return keys.reduce(\n (acc, key) => {\n // @ts-ignore\n acc[definition[key].value] = definition[key][prop];\n return acc;\n },\n {} as Record<E[keyof E]['value'], A[P]>,\n );\n },\n } as unknown as DictExpose<A, E>;\n}\n\n/**\n * 声明一个枚举工厂函数\n * @template A - 枚举元数据附加类型,扩展自 DictMetaAppend\n * @returns {Object} 返回包含 define 方法的对象\n *\n * @property {function} define - 定义枚举的函数\n * @template E - 枚举描述类型\n * @param {_CheckDefinition<E>} definition - 枚举定义对象\n * @returns {DictExpose<A, E>} 返回枚举的完整暴露对象\n * @example\n * ```typescript\n * const createStatusDict = declareDict<{ label: string }>();\n * const Status = createStatusDict.define({\n * Pending: { value: 0, label: '待处理' },\n * Approved: { value: 1, label: '已批准' }\n * });\n * ```\n */\nexport function declareDict<A extends DictMetaAppend>() {\n return {\n define<const E extends DictDescription<A>>(definition: _CheckDefinition<E>): DictExpose<A, E> {\n return _defineDict(definition);\n },\n };\n}\n"],"names":[],"mappings":"AAuFA,SAAS,YACP,YACkB;AACZ,QAAA,OAAO,OAAO,KAAK,UAAU;AAE5B,SAAA;AAAA,IACL,GAAG,CAAC,GAAG,OAAO,QAAQ,UAAU,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM;AAC7D,UAAI,IAAI,CAAC,EAAE,kBAAkB,IAAI,CAAC,GAAG;AACnC,cAAM,IAAI,MAAM,WAAW,GAAG,YAAY;AAAA,MAAA;AAGxC,UAAA,IAAI,WAAW,GAAG,GAAG;AACvB,cAAM,IAAI,MAAM,WAAW,GAAG,aAAa;AAAA,MAAA;AAIzC,UAAA,GAAG,IAAI,IAAI;AAEf,UAAI,IAAI,GAAG,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI;AACxB,aAAA;AAAA,IACT,GAAG,EAAE;AAAA,IACL;AAAA,IACA,cAAc,KAAK,IAAI,CAAC,SAAS;AAAA,MAC/B;AAAA,MACA,GAAG,WAAW,GAAG;AAAA,IAAA,EACjB;AAAA,IACF;AAAA,IACA,QAAQ,KAAK;AAAA,IACb,QAAQ,KAAK,IAAI,CAAC,QAAQ,WAAW,GAAc,EAAE,KAAK;AAAA,IAC1D,UAAU,KAAK,OAAO,CAAC,KAAK,QAAQ;AAElC,UAAI,GAAG,IAAI,WAAW,GAAG,EAAE;AACpB,aAAA;AAAA,IACT,GAAG,EAAE;AAAA,IACL,UAAU,KAAK,OAAO,CAAC,KAAK,QAAQ;AAElC,UAAI,WAAW,GAAG,EAAE,KAAK,IAAI;AACtB,aAAA;AAAA,IACT,GAAG,EAAE;AAAA,IACL,YAA+B,MAAS;AACtC,aAAO,KAAK,OAAO,CAAC,KAAK,QAAQ;AAE/B,YAAI,GAAG,IAAI,WAAW,GAAG,EAAE,IAAI;AACxB,eAAA;AAAA,MACT,GAAG,EAAE;AAAA,IACP;AAAA,IACA,YAA+B,MAAS;AACtC,aAAO,KAAK;AAAA,QACV,CAAC,KAAK,QAAQ;AAER,cAAA,WAAW,GAAG,EAAE,KAAK,IAAI,WAAW,GAAG,EAAE,IAAI;AAC1C,iBAAA;AAAA,QACT;AAAA,QACA,CAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAEJ;AACF;AAoBO,SAAS,cAAwC;AAC/C,SAAA;AAAA,IACL,OAA2C,YAAmD;AAC5F,aAAO,YAAY,UAAU;AAAA,IAAA;AAAA,EAEjC;AACF;"}
|
|
1
|
+
{"version":3,"file":"dict.mjs","sources":["../src/dict.ts"],"sourcesContent":["import type { AnyObject, MergeIntersection, UnionToIntersection, UnionToTuple } from './types';\n\nexport type DictKey = string;\nexport type DictValue = number | string;\nexport type DictMetaAppend = {\n key?: string;\n value?: string | number;\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n [key: string]: any;\n};\nexport type DictMeta<A extends DictMetaAppend> = A & {\n value: DictValue;\n};\nexport type DictDescription<A extends DictMetaAppend> = Record<DictKey, DictMeta<A>>;\n\nconst dictError = Symbol('dictKeyError');\n\ntype _StartWithDollarSign<T extends string> = T extends `$${infer R}` ? R : never;\n\ntype _CheckDefinition<O extends AnyObject> = {\n // [K in keyof O & string]: K extends Capitalize<K> ? O[K] : `错误:枚举键名 ${K} 必须大写字母开头`;\n [K in keyof O & string]: K extends Capitalize<K>\n ? K extends `$${infer R}`\n ? O[K] & { [dictError]: `错误:枚举键名 ${K} 不能以 $ 符号开头` }\n : O[K]\n : O[K] & { [dictError]: `错误:枚举键名 ${K} 必须以大写字母开头` };\n};\n\ntype _ToOriginDefProp<T extends AnyObject> = {\n [K in keyof T as `$${K & string}`]: MergeIntersection<T[K] & { readonly key: K }>;\n};\n\ntype _KVRecord<T> = T extends Record<string, AnyObject>\n ? {\n readonly [K in keyof T]: T[K]['value'];\n }\n : never;\n\ntype _VKRecord<T> = T extends Record<string, AnyObject>\n ? MergeIntersection<\n UnionToIntersection<\n {\n [K in keyof T]: {\n [P in keyof T[K] as P extends 'value' ? T[K][P] & (string | number) : never]: K;\n };\n }[keyof T]\n >\n >\n : never;\n\nexport type DictExpose<A extends DictMetaAppend, E extends DictDescription<A>> = _ToOriginDefProp<E> &\n _KVRecord<E> & {\n readonly definition: E;\n readonly descriptions: MergeIntersection<A & { key: keyof E; value: E[keyof E]['value'] }>[];\n readonly keys: UnionToTuple<keyof E>;\n readonly length: UnionToTuple<keyof E>['length'];\n readonly values: UnionToTuple<E[keyof E]['value']>;\n readonly kvRecord: _KVRecord<E>;\n readonly vkRecord: _VKRecord<E>;\n toKeyRecord: <P extends keyof A>(prop: P) => Record<keyof E, A[P]>;\n toValRecord: <P extends keyof A>(prop: P) => Record<E[keyof E]['value'], A[P]>;\n };\n\n/**\n * 定义一个枚举类型,如果需要类型提示,需要使用 declareDict 函数定义枚举。\n * @template A - 枚举元数据附加类型,扩展自 DictMetaAppend\n * @template E - 枚举描述类型,键为枚举键名,值为枚举元数据\n * @param {_CheckDefinition<E>} definition - 枚举定义对象\n * @returns {DictExpose<A, E>} 返回枚举的完整暴露对象\n * @example\n * ```typescript\n * const Status = defineDict({\n * Pending: { value: 0, label: '待处理' },\n * Approved: { value: 1, label: '已批准' }\n * });\n * ```\n *\n * @property {E} definition - 原始枚举定义对象\n * @property {Array<MergeIntersection<A & { key: keyof E }>>} descriptions - 枚举项的完整描述数组\n * @property {UnionToTuple<keyof E>} keys - 枚举键名的元组\n * @property {\"UnionToTuple<keyof E>[\\\"length\\\"]\"} length - 枚举项的数量\n * @property {UnionToTuple<E[keyof E][\"value\"]>} values - 枚举值的元组\n * @property {Record<keyof E, E[keyof E][\"value\"]>} kvRecord - 键到值的映射记录\n * @property {Record<E[keyof E][\"value\"], E[keyof E]>} vkRecord - 值到键的映射记录\n * @property {function} toKeyRecord - 根据属性名创建键到属性值的映射记录\n * @property {function} toValueRecord - 根据属性名创建值到属性值的映射记录\n */\nfunction _defineDict<A extends DictMetaAppend, const E extends DictDescription<A>>(\n definition: _CheckDefinition<E>,\n): DictExpose<A, E> {\n const keys = Object.keys(definition);\n\n return {\n ...[...Object.entries(definition)].reduce((acc, [key, dfn]) => {\n if (key[0].toUpperCase() !== key[0]) {\n throw new Error(`错误:枚举键名 ${key} 必须以大写字母开头`);\n }\n\n if (key.startsWith('$')) {\n throw new Error(`错误:枚举键名 ${key} 不能以 $ 符号开头`);\n }\n\n // @ts-ignore\n acc[key] = dfn.value;\n // @ts-ignore\n acc[`$${key}`] = { key, ...dfn };\n return acc;\n }, {}),\n definition,\n descriptions: keys.map((key) => ({\n key,\n ...definition[key],\n })),\n keys,\n length: keys.length,\n values: keys.map((key) => definition[key as keyof E].value),\n kvRecord: keys.reduce((acc, key) => {\n // @ts-ignore\n acc[key] = definition[key].value;\n return acc;\n }, {}),\n vkRecord: keys.reduce((acc, key) => {\n // @ts-ignore\n acc[definition[key].value] = key;\n return acc;\n }, {}),\n toKeyRecord<P extends keyof A>(prop: P) {\n return keys.reduce((acc, key) => {\n // @ts-ignore\n acc[key] = definition[key][prop];\n return acc;\n }, {});\n },\n toValRecord<P extends keyof A>(prop: P) {\n return keys.reduce(\n (acc, key) => {\n // @ts-ignore\n acc[definition[key].value] = definition[key][prop];\n return acc;\n },\n {} as Record<E[keyof E]['value'], A[P]>,\n );\n },\n } as unknown as DictExpose<A, E>;\n}\n\n/**\n * 声明一个枚举工厂函数\n * @template A - 枚举元数据附加类型,扩展自 DictMetaAppend\n * @returns {Object} 返回包含 define 方法的对象\n *\n * @property {function} define - 定义枚举的函数\n * @template E - 枚举描述类型\n * @param {_CheckDefinition<E>} definition - 枚举定义对象\n * @returns {DictExpose<A, E>} 返回枚举的完整暴露对象\n * @example\n * ```typescript\n * const createStatusDict = declareDict<{ label: string }>();\n * const Status = createStatusDict.define({\n * Pending: { value: 0, label: '待处理' },\n * Approved: { value: 1, label: '已批准' }\n * });\n * ```\n */\nexport function declareDict<A extends DictMetaAppend>() {\n return {\n define<const E extends DictDescription<A>>(definition: _CheckDefinition<E>): DictExpose<A, E> {\n return _defineDict(definition);\n },\n };\n}\n"],"names":[],"mappings":"AAuFA,SAAS,YACP,YACkB;AACZ,QAAA,OAAO,OAAO,KAAK,UAAU;AAE5B,SAAA;AAAA,IACL,GAAG,CAAC,GAAG,OAAO,QAAQ,UAAU,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM;AAC7D,UAAI,IAAI,CAAC,EAAE,kBAAkB,IAAI,CAAC,GAAG;AACnC,cAAM,IAAI,MAAM,WAAW,GAAG,YAAY;AAAA,MAAA;AAGxC,UAAA,IAAI,WAAW,GAAG,GAAG;AACvB,cAAM,IAAI,MAAM,WAAW,GAAG,aAAa;AAAA,MAAA;AAIzC,UAAA,GAAG,IAAI,IAAI;AAEf,UAAI,IAAI,GAAG,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI;AACxB,aAAA;AAAA,IACT,GAAG,EAAE;AAAA,IACL;AAAA,IACA,cAAc,KAAK,IAAI,CAAC,SAAS;AAAA,MAC/B;AAAA,MACA,GAAG,WAAW,GAAG;AAAA,IAAA,EACjB;AAAA,IACF;AAAA,IACA,QAAQ,KAAK;AAAA,IACb,QAAQ,KAAK,IAAI,CAAC,QAAQ,WAAW,GAAc,EAAE,KAAK;AAAA,IAC1D,UAAU,KAAK,OAAO,CAAC,KAAK,QAAQ;AAElC,UAAI,GAAG,IAAI,WAAW,GAAG,EAAE;AACpB,aAAA;AAAA,IACT,GAAG,EAAE;AAAA,IACL,UAAU,KAAK,OAAO,CAAC,KAAK,QAAQ;AAElC,UAAI,WAAW,GAAG,EAAE,KAAK,IAAI;AACtB,aAAA;AAAA,IACT,GAAG,EAAE;AAAA,IACL,YAA+B,MAAS;AACtC,aAAO,KAAK,OAAO,CAAC,KAAK,QAAQ;AAE/B,YAAI,GAAG,IAAI,WAAW,GAAG,EAAE,IAAI;AACxB,eAAA;AAAA,MACT,GAAG,EAAE;AAAA,IACP;AAAA,IACA,YAA+B,MAAS;AACtC,aAAO,KAAK;AAAA,QACV,CAAC,KAAK,QAAQ;AAER,cAAA,WAAW,GAAG,EAAE,KAAK,IAAI,WAAW,GAAG,EAAE,IAAI;AAC1C,iBAAA;AAAA,QACT;AAAA,QACA,CAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAEJ;AACF;AAoBO,SAAS,cAAwC;AAC/C,SAAA;AAAA,IACL,OAA2C,YAAmD;AAC5F,aAAO,YAAY,UAAU;AAAA,IAAA;AAAA,EAEjC;AACF;"}
|
package/dist/index.cjs
CHANGED
package/dist/index.mjs
CHANGED
package/dist/number.d.ts
CHANGED
|
@@ -137,10 +137,10 @@ export type NumberFormatOptions = {
|
|
|
137
137
|
* // 使用对象配置
|
|
138
138
|
* numberFormat(123456.789, { separator: '.', step: 4 }); // => "12.3456.789"
|
|
139
139
|
*/
|
|
140
|
-
export declare function numberFormat(number: number, options: NumberFormatOptions): string;
|
|
141
|
-
export declare function numberFormat(number: number, separator: string): string;
|
|
142
|
-
export declare function numberFormat(number: number, step: number): string;
|
|
143
|
-
export declare function numberFormat(number: number): string;
|
|
140
|
+
export declare function numberFormat(number: number | string, options: NumberFormatOptions): string;
|
|
141
|
+
export declare function numberFormat(number: number | string, separator: string): string;
|
|
142
|
+
export declare function numberFormat(number: number | string, step: number): string;
|
|
143
|
+
export declare function numberFormat(number: number | string): string;
|
|
144
144
|
/**
|
|
145
145
|
* 将数字限制在指定范围内。
|
|
146
146
|
*
|
package/dist/string2.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"string2.cjs","sources":["../src/number.ts","../src/string.ts"],"sourcesContent":["import { objectDefaults } from './object';\nimport { STRING_DICT } from './string';\nimport { isNumber } from './type';\n\nexport type NumberFixedOptions = {\n /**\n * 保留的小数位数\n * @default 0\n */\n decimals?: number;\n\n /**\n * 舍入方法,0 为四舍五入,1 为向上取整,-1 为向下取整\n * @default 0\n */\n round?: 0 | 1 | -1;\n};\n\n/**\n * 对数字进行精确小数位数处理并按规则舍入\n * @param number 需要处理的原始数值\n * @param options 可选配置参数\n * @returns 处理后的数值(number类型)\n * @example\n * // 四舍五入示例\n * numberFixed(3.1415, { decimals: 2 }); // 3.14\n * // 向上取整示例\n * numberFixed(3.1415, { decimals: 2, round: 1 }); // 3.15\n * // 向下取整示例\n * numberFixed(3.9999, { decimals: 1, round: -1 }); // 3.9\n */\nexport function numberFixed(number: number, options?: NumberFixedOptions) {\n const { decimals = 0, round = 0 } = options || {};\n const scale = 10 ** decimals;\n\n if (round === 1) {\n return Math.ceil(number * scale) / scale;\n }\n\n if (round === -1) {\n return Math.floor(number * scale) / scale;\n }\n\n return Math.round(number * scale) / scale;\n}\n\n/**\n * 生成指定范围内的随机数\n * @param {number | string} min - 随机数的最小值(包含,支持小数、字符串)\n * @param {number | string} max - 随机数的最大值(包含,支持小数、字符串)\n * @returns {number} - 生成的随机数\n * @example\n * // 生成 1 到 10 之间的随机整数\n * randomNumber(1, 10); // 可能返回 7\n *\n * // 生成 0.1 到 2 之间的一位随机小数\n * randomNumber(0.1, 2); // 可能返回 0.7\n *\n * // 生成 0.10 到 2 之间的两位随机小数\n * randomNumber(\"0.10\", 2); // 可能返回 0.75\n */\nexport function randomNumber(min: number | string, max: number | string): number {\n const minDecimals = numberDecimals(min);\n const maxDecimals = numberDecimals(max);\n const decimals = Math.max(minDecimals, maxDecimals);\n const scale = 10 ** decimals;\n\n const minNum = Number(min);\n const maxNum = Number(max);\n const [minFinal, maxFinal] = minNum > maxNum ? [maxNum, minNum] : [minNum, maxNum];\n\n const scaledMin = minFinal * scale;\n const scaledMax = maxFinal * scale;\n\n return Math.floor(Math.random() * (scaledMax - scaledMin + 1) + scaledMin) / scale;\n}\n\n/**\n * 数字缩写选项\n */\nexport type NumberAbbrOptions = {\n /**\n * 进制基数,用于计算单位进阶(如 1000 表示千进制)\n * @default 1000\n */\n base?: number;\n\n /**\n * 数值保留的小数位数\n * @default 0\n */\n decimals?: number;\n};\n\n/**\n * 将数字转换为带单位缩写的字符串表示\n *\n * @param {number} number - 需要转换的原始数值\n * @param {Array<string>} units - 单位数组,按从小到大顺序排列(如['B','KB','MB']),不能为空\n * @param {NumberAbbrOptions} [options] - 可选配置参数\n * @returns {string} - 转换后的带单位字符串(如\"1.2KB\")\n * @example\n * // 基础用法\n * numberAbbr(1500, ['', 'K', 'M'], { base: 1000 }); // \"1.5K\"\n * @example\n * // 自定义小数位\n * numberAbbr(123456, ['B','KB','MB'], { decimals: 1 }); // \"0.1MB\"\n * @example\n * // 处理不足基数的情况\n * numberAbbr(500, ['B','KB']); // \"500B\"\n */\nexport function numberAbbr(number: number, units: Array<string>, options?: NumberAbbrOptions): string {\n const { base = 1000, decimals = 0 } = options || {};\n const { length } = units;\n\n if (length === 0) throw new Error('数字单位组不能为空');\n\n let numberFinal = number;\n let step = 0;\n\n while (numberFinal >= base && step < length - 1) {\n numberFinal = numberFinal / base;\n step++;\n }\n\n const value = numberFixed(numberFinal, { decimals: decimals, round: -1 });\n const unit = units[step];\n\n return `${value}${unit}`;\n}\n\n/**\n * 将文件大小转换为带单位缩写的字符串表示\n *\n * @param {number} number - 需要转换的文件大小数值\n * @param {number} [decimals=0] - 数值保留的小数位数\n * @returns {string} - 转换后的带单位字符串(如\"1.2KB\")\n * @example\n * // 基础用法\n * fileSizeAbbr(1024); // \"1KB\"\n * @example\n * // 自定义小数位\n * fileSizeAbbr(123456, 1); // \"0.1MB\"\n */\nexport function fileSizeAbbr(number: number, decimals = 0) {\n return numberAbbr(number, ['B', 'KB', 'MB', 'GB', 'TB'], {\n base: 1024,\n decimals: decimals,\n });\n}\n\n/**\n * 将十进制数转换为指定进制的字符串表示\n *\n * @param {number | bigint} decimal - 需要转换的十进制数,可以是任意长度的数字或大整数\n * @param {string} [dict] - 用于表示进制的字符字典,默认为数字、小写字母和大写字母的组合(62 进制)\n * @returns {string} - 转换后的指定进制字符串\n * @throws {Error} - 如果字符字典的长度小于 2,将抛出错误\n * @example\n * // 默认 62 进制\n * numberConvert(123456789); // \"8M0kX\"\n * @example\n * // 自定义 16 进制\n * numberConvert(255, '0123456789ABCDEF'); // \"FF\"\n * @example\n * // 处理大整数\n * numberConvert(9007199254740991n); // \"2gosa7pa2GV\"\n */\nexport function numberConvert(decimal: number | bigint, dict?: string): string {\n const dictFinal = dict || STRING_DICT;\n\n if (dictFinal.length < 2) throw new Error('进制转换字典长度不能小于 2');\n\n let bigInt = BigInt(decimal);\n const symbol = bigInt < 0n ? '-' : '';\n bigInt = bigInt < 0n ? -bigInt : bigInt;\n const result: Array<string> = [];\n const { length } = dictFinal;\n const bigLength = BigInt(length);\n const calculate = (): void => {\n const y = Number(bigInt % bigLength);\n\n bigInt = bigInt / bigLength;\n result.unshift(dictFinal[y]);\n\n if (bigInt > 0) {\n calculate();\n }\n };\n\n calculate();\n\n return symbol + result.join('');\n}\n\n/**\n * 数字格式化配置选项\n */\nexport type NumberFormatOptions = {\n /**\n * 分隔符字符,用于数字分隔\n * @default ','\n * @example 使用 '_' 分隔符时,123456 会格式化为 '123_456'\n */\n separator?: string;\n\n /**\n * 分隔步长,即每隔多少位添加分隔符\n * @default 3\n * @example 步长为 2 时,123456 会格式化为 '12,34,56'\n */\n step?: number;\n};\n\n/**\n * 数字格式化\n * @param [number] {number} 数字\n * @param options {NumberFormatOptions} 格式化配置\n * @returns {string} 分割后的字符串\n * @example\n * // 使用默认分隔符和步长\n * numberFormat(123456.789); // => \"123,456.789\"\n * // 自定义分隔符\n * numberFormat(123456.789, '_'); // => \"123_456.789\"\n * // 自定义步长\n * numberFormat(123456.789, 2); // => \"12,34,56.789\"\n * // 使用对象配置\n * numberFormat(123456.789, { separator: '.', step: 4 }); // => \"12.3456.789\"\n */\nexport function numberFormat(number: number, options: NumberFormatOptions): string;\nexport function numberFormat(number: number, separator: string): string;\nexport function numberFormat(number: number, step: number): string;\nexport function numberFormat(number: number): string;\nexport function numberFormat(number: number, options?: NumberFormatOptions | string | number) {\n let optionsFinal: Required<NumberFormatOptions> = {\n separator: ',',\n step: 3,\n };\n\n if (typeof options === 'string') {\n optionsFinal.separator = options;\n } else if (typeof options === 'number') {\n optionsFinal.step = options;\n } else {\n optionsFinal = objectDefaults(options || {}, optionsFinal) as Required<NumberFormatOptions>;\n }\n\n const { separator, step } = optionsFinal;\n const arr = String(number).split('.');\n const re = new RegExp(`(\\\\d)(?=(\\\\d{${step}})+(?!\\\\d))`, 'g');\n const p1 = arr[0].replace(re, `$1${separator}`);\n\n return p1 + (arr[1] ? `.${arr[1]}` : '');\n}\n\n/**\n * 将数字限制在指定范围内。\n *\n * @param min - 最小值。\n * @param number - 要限制的数字。\n * @param max - 最大值。\n * @returns 限制后的数字。\n */\nexport function numberClamp(min: number, number: number, max: number) {\n return Math.min(Math.max(number, min), max);\n}\n\n/**\n * 为数字添加单位\n * @param number - 需要处理的数字,可以是数字类型或字符串类型\n * @param unit - 要添加的单位,默认为空字符串\n * @returns 如果输入是数字或纯数字字符串,则返回带单位的字符串;否则返回原值\n */\nexport function numberUnit(number: string | number, unit = '') {\n if (isNumber(number)) return `${number}${unit}`;\n if (/^-?[\\d.]+$/.test(number)) return `${number}${unit}`;\n return number;\n}\n\n/**\n * 获取数字的小数位数\n * @param num - 需要计算小数位数的数字或数字字符串\n * @returns 返回数字的小数位数,如果是整数则返回0\n * @example\n * // 基本用法\n * numberDecimals(3.1415); // 4\n * numberDecimals(\"3.1415\"); // 4\n * numberDecimals(100); // 0\n * numberDecimals(\"100\"); // 0\n * // 科学计数法\n * numberDecimals(\"1.23e-4\"); // 6\n */\nexport function numberDecimals(num: number | string) {\n const numStr = String(num);\n const matches = numStr.match(/(?:\\.(\\d+))?(?:e-(\\d+))?$/i);\n if (!matches) return 0;\n return (matches[1] || '').length + Number.parseInt(matches[2] || '0');\n}\n","import { numberConvert, randomNumber } from './number';\nimport { isFunction, isNullish, isNumber, isObject, isString, isUndefined } from './type';\n\n/** 阿拉伯数字字符集合 */\nexport const STRING_ARABIC_NUMERALS = '0123456789';\n/** 十六进制字符集合 */\nexport const STRING_HEXADECIMALS = '0123456789abcdef';\n/** 小写字母字符集合 */\nexport const STRING_LOWERCASE_ALPHA = 'abcdefghijklmnopqrstuvwxyz';\n/** 大写字母字符集合 */\nexport const STRING_UPPERCASE_ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\n/** 随机字符串字典,包含数字、大写字母和小写字母 */\nexport const STRING_DICT = `${STRING_ARABIC_NUMERALS + STRING_UPPERCASE_ALPHA + STRING_LOWERCASE_ALPHA}`;\n\n/**\n * 将字符串转换为驼峰格式\n * @param {string} string - 要转换的字符串\n * @param {boolean} [bigger] - 是否大写第一个字母,默认为 false\n * @returns {string} - 转换后的驼峰格式字符串\n */\nexport function stringCamelCase(string: string, bigger?: boolean): string {\n const string2 = string.replace(/[\\s_-](.)/g, (_, char) => (char as string).toUpperCase());\n return bigger ? string2.slice(0, 1).toUpperCase() + string2.slice(1) : string2;\n}\n\n/**\n * 将字符串转换为连字格式\n * @param {string} string - 要转换的字符串\n * @param {string} [separator] - 分隔符,默认是 \"-\"(短横线)\n * @returns {string} - 转换后的连字格式字符串\n */\nexport function stringKebabCase(string: string, separator = '-'): string {\n return string.replace(/[A-Z]/g, (origin) => `${separator}${origin.toLowerCase()}`);\n}\n\n/**\n * 生成随机字符串\n * @param {number} length - 生成的随机字符串长度\n * @param {string} [dict] - 用于生成随机字符串的字符字典,默认为数字、小写字母和大写字母的组合\n * @returns {string} - 生成的随机字符串\n * @example\n * randomString(10); // 生成一个长度为 10 的随机字符串\n * randomString(8, 'ABCDEF'); // 生成一个长度为 8 的随机字符串,仅包含字符 'ABCDEF'\n */\nexport function randomString(length: number, dict?: string): string {\n const dictFinal = dict || STRING_DICT;\n const dictLength = dictFinal.length;\n\n let result = '';\n\n for (let i = 0; i < length; i++) {\n result += dictFinal.charAt(randomNumber(0, dictLength - 1));\n }\n\n return result;\n}\n\n/**\n * 简单的模板引擎,类似于 Python 的 `.format()` 方法\n * 支持通过索引或对象/名称的方式传递变量\n * 当使用对象/名称方式时,可以传递一个回退值作为第三个参数\n *\n * @category 字符串\n * @example\n * ```\n * // 索引方式\n * const result = stringFormat(\n * '你好 {0}!我的名字是 {1}。',\n * '张三',\n * '李四'\n * ); // 你好 张三!我的名字是 李四。\n * ```\n *\n * @example\n * ```\n * // 对象方式\n * const result = stringFormat(\n * '{greet}!我的名字是 {name}。',\n * { greet: '你好', name: '王五' }\n * ); // 你好!我的名字是 王五。\n * ```\n *\n * @example\n * ```\n * // 带回退值的对象方式\n * const result = stringFormat(\n * '{greet}!我的名字是 {name}。',\n * { greet: '你好' }, // name 未传递,因此会使用回退值\n * '未知'\n * ); // 你好!我的名字是 未知。\n * ```\n */\nexport function stringFormat(\n str: string,\n object: Record<string | number, unknown>,\n fallback?: string | ((key: string) => string),\n): string;\nexport function stringFormat(str: string, ...args: (string | number | bigint | undefined | null)[]): string;\nexport function stringFormat(str: string, ...args: unknown[]): string {\n const [firstArg, fallback] = args;\n\n if (isObject(firstArg) || isUndefined(firstArg)) {\n const vars = firstArg || {};\n return str.replace(/\\{(\\w+)\\}/g, (_, key) => vars[key] ?? (isFunction(fallback) ? fallback(key) : fallback) ?? key);\n }\n\n return str.replace(/\\{(\\d+)\\}/g, (_, key) => {\n const index = Number(key);\n if (Number.isNaN(index)) return key;\n return args[index];\n });\n}\n\n/**\n * 生成符合 [RFC 4122](https://www.ietf.org/rfc/rfc4122.txt) 版本 4 的 UUID 字符串\n * @returns {string} - 生成的 UUID 字符串\n * @example\n * const uuid = randomUUID4();\n * console.log(uuid); // 输出类似 '123e4567-e89b-12d3-a456-426614174000' 的 UUID 字符串\n */\nexport function randomUUID4(): string {\n const template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';\n let result = '';\n\n for (let i = 0; i < template.length; i++) {\n const t = template[i];\n\n if (t === '-' || t === '4') {\n result += t;\n continue;\n }\n\n if (t === 'y') {\n result += randomString(1, '89ab');\n continue;\n }\n\n result += randomString(1, STRING_HEXADECIMALS);\n }\n\n return result;\n}\n\n/**\n * 将值转换为字符串,若值为 null 或 undefined 则返回空字符串\n * @param {unknown} value - 需要转换的值\n * @returns {string} 转换后的字符串结果\n */\nexport function stringify(value: unknown) {\n return isNullish(value) ? '' : String(value);\n}\n"],"names":["objectDefaults","isNumber","isObject","isUndefined","isFunction","isNullish"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"string2.cjs","sources":["../src/number.ts","../src/string.ts"],"sourcesContent":["import { objectDefaults } from './object';\nimport { STRING_DICT } from './string';\nimport { isNumber } from './type';\n\nexport type NumberFixedOptions = {\n /**\n * 保留的小数位数\n * @default 0\n */\n decimals?: number;\n\n /**\n * 舍入方法,0 为四舍五入,1 为向上取整,-1 为向下取整\n * @default 0\n */\n round?: 0 | 1 | -1;\n};\n\n/**\n * 对数字进行精确小数位数处理并按规则舍入\n * @param number 需要处理的原始数值\n * @param options 可选配置参数\n * @returns 处理后的数值(number类型)\n * @example\n * // 四舍五入示例\n * numberFixed(3.1415, { decimals: 2 }); // 3.14\n * // 向上取整示例\n * numberFixed(3.1415, { decimals: 2, round: 1 }); // 3.15\n * // 向下取整示例\n * numberFixed(3.9999, { decimals: 1, round: -1 }); // 3.9\n */\nexport function numberFixed(number: number, options?: NumberFixedOptions) {\n const { decimals = 0, round = 0 } = options || {};\n const scale = 10 ** decimals;\n\n if (round === 1) {\n return Math.ceil(number * scale) / scale;\n }\n\n if (round === -1) {\n return Math.floor(number * scale) / scale;\n }\n\n return Math.round(number * scale) / scale;\n}\n\n/**\n * 生成指定范围内的随机数\n * @param {number | string} min - 随机数的最小值(包含,支持小数、字符串)\n * @param {number | string} max - 随机数的最大值(包含,支持小数、字符串)\n * @returns {number} - 生成的随机数\n * @example\n * // 生成 1 到 10 之间的随机整数\n * randomNumber(1, 10); // 可能返回 7\n *\n * // 生成 0.1 到 2 之间的一位随机小数\n * randomNumber(0.1, 2); // 可能返回 0.7\n *\n * // 生成 0.10 到 2 之间的两位随机小数\n * randomNumber(\"0.10\", 2); // 可能返回 0.75\n */\nexport function randomNumber(min: number | string, max: number | string): number {\n const minDecimals = numberDecimals(min);\n const maxDecimals = numberDecimals(max);\n const decimals = Math.max(minDecimals, maxDecimals);\n const scale = 10 ** decimals;\n\n const minNum = Number(min);\n const maxNum = Number(max);\n const [minFinal, maxFinal] = minNum > maxNum ? [maxNum, minNum] : [minNum, maxNum];\n\n const scaledMin = minFinal * scale;\n const scaledMax = maxFinal * scale;\n\n return Math.floor(Math.random() * (scaledMax - scaledMin + 1) + scaledMin) / scale;\n}\n\n/**\n * 数字缩写选项\n */\nexport type NumberAbbrOptions = {\n /**\n * 进制基数,用于计算单位进阶(如 1000 表示千进制)\n * @default 1000\n */\n base?: number;\n\n /**\n * 数值保留的小数位数\n * @default 0\n */\n decimals?: number;\n};\n\n/**\n * 将数字转换为带单位缩写的字符串表示\n *\n * @param {number} number - 需要转换的原始数值\n * @param {Array<string>} units - 单位数组,按从小到大顺序排列(如['B','KB','MB']),不能为空\n * @param {NumberAbbrOptions} [options] - 可选配置参数\n * @returns {string} - 转换后的带单位字符串(如\"1.2KB\")\n * @example\n * // 基础用法\n * numberAbbr(1500, ['', 'K', 'M'], { base: 1000 }); // \"1.5K\"\n * @example\n * // 自定义小数位\n * numberAbbr(123456, ['B','KB','MB'], { decimals: 1 }); // \"0.1MB\"\n * @example\n * // 处理不足基数的情况\n * numberAbbr(500, ['B','KB']); // \"500B\"\n */\nexport function numberAbbr(number: number, units: Array<string>, options?: NumberAbbrOptions): string {\n const { base = 1000, decimals = 0 } = options || {};\n const { length } = units;\n\n if (length === 0) throw new Error('数字单位组不能为空');\n\n let numberFinal = number;\n let step = 0;\n\n while (numberFinal >= base && step < length - 1) {\n numberFinal = numberFinal / base;\n step++;\n }\n\n const value = numberFixed(numberFinal, { decimals: decimals, round: -1 });\n const unit = units[step];\n\n return `${value}${unit}`;\n}\n\n/**\n * 将文件大小转换为带单位缩写的字符串表示\n *\n * @param {number} number - 需要转换的文件大小数值\n * @param {number} [decimals=0] - 数值保留的小数位数\n * @returns {string} - 转换后的带单位字符串(如\"1.2KB\")\n * @example\n * // 基础用法\n * fileSizeAbbr(1024); // \"1KB\"\n * @example\n * // 自定义小数位\n * fileSizeAbbr(123456, 1); // \"0.1MB\"\n */\nexport function fileSizeAbbr(number: number, decimals = 0) {\n return numberAbbr(number, ['B', 'KB', 'MB', 'GB', 'TB'], {\n base: 1024,\n decimals: decimals,\n });\n}\n\n/**\n * 将十进制数转换为指定进制的字符串表示\n *\n * @param {number | bigint} decimal - 需要转换的十进制数,可以是任意长度的数字或大整数\n * @param {string} [dict] - 用于表示进制的字符字典,默认为数字、小写字母和大写字母的组合(62 进制)\n * @returns {string} - 转换后的指定进制字符串\n * @throws {Error} - 如果字符字典的长度小于 2,将抛出错误\n * @example\n * // 默认 62 进制\n * numberConvert(123456789); // \"8M0kX\"\n * @example\n * // 自定义 16 进制\n * numberConvert(255, '0123456789ABCDEF'); // \"FF\"\n * @example\n * // 处理大整数\n * numberConvert(9007199254740991n); // \"2gosa7pa2GV\"\n */\nexport function numberConvert(decimal: number | bigint, dict?: string): string {\n const dictFinal = dict || STRING_DICT;\n\n if (dictFinal.length < 2) throw new Error('进制转换字典长度不能小于 2');\n\n let bigInt = BigInt(decimal);\n const symbol = bigInt < 0n ? '-' : '';\n bigInt = bigInt < 0n ? -bigInt : bigInt;\n const result: Array<string> = [];\n const { length } = dictFinal;\n const bigLength = BigInt(length);\n const calculate = (): void => {\n const y = Number(bigInt % bigLength);\n\n bigInt = bigInt / bigLength;\n result.unshift(dictFinal[y]);\n\n if (bigInt > 0) {\n calculate();\n }\n };\n\n calculate();\n\n return symbol + result.join('');\n}\n\n/**\n * 数字格式化配置选项\n */\nexport type NumberFormatOptions = {\n /**\n * 分隔符字符,用于数字分隔\n * @default ','\n * @example 使用 '_' 分隔符时,123456 会格式化为 '123_456'\n */\n separator?: string;\n\n /**\n * 分隔步长,即每隔多少位添加分隔符\n * @default 3\n * @example 步长为 2 时,123456 会格式化为 '12,34,56'\n */\n step?: number;\n};\n\n/**\n * 数字格式化\n * @param [number] {number} 数字\n * @param options {NumberFormatOptions} 格式化配置\n * @returns {string} 分割后的字符串\n * @example\n * // 使用默认分隔符和步长\n * numberFormat(123456.789); // => \"123,456.789\"\n * // 自定义分隔符\n * numberFormat(123456.789, '_'); // => \"123_456.789\"\n * // 自定义步长\n * numberFormat(123456.789, 2); // => \"12,34,56.789\"\n * // 使用对象配置\n * numberFormat(123456.789, { separator: '.', step: 4 }); // => \"12.3456.789\"\n */\nexport function numberFormat(number: number | string, options: NumberFormatOptions): string;\nexport function numberFormat(number: number | string, separator: string): string;\nexport function numberFormat(number: number | string, step: number): string;\nexport function numberFormat(number: number | string): string;\nexport function numberFormat(number: number | string, options?: NumberFormatOptions | string | number) {\n let optionsFinal: Required<NumberFormatOptions> = {\n separator: ',',\n step: 3,\n };\n\n if (typeof options === 'string') {\n optionsFinal.separator = options;\n } else if (typeof options === 'number') {\n optionsFinal.step = options;\n } else {\n optionsFinal = objectDefaults(options || {}, optionsFinal) as Required<NumberFormatOptions>;\n }\n\n const { separator, step } = optionsFinal;\n const arr = String(number).split('.');\n const re = new RegExp(`(\\\\d)(?=(\\\\d{${step}})+(?!\\\\d))`, 'g');\n const p1 = arr[0].replace(re, `$1${separator}`);\n\n return p1 + (arr[1] ? `.${arr[1]}` : '');\n}\n\n/**\n * 将数字限制在指定范围内。\n *\n * @param min - 最小值。\n * @param number - 要限制的数字。\n * @param max - 最大值。\n * @returns 限制后的数字。\n */\nexport function numberClamp(min: number, number: number, max: number) {\n return Math.min(Math.max(number, min), max);\n}\n\n/**\n * 为数字添加单位\n * @param number - 需要处理的数字,可以是数字类型或字符串类型\n * @param unit - 要添加的单位,默认为空字符串\n * @returns 如果输入是数字或纯数字字符串,则返回带单位的字符串;否则返回原值\n */\nexport function numberUnit(number: string | number, unit = '') {\n if (isNumber(number)) return `${number}${unit}`;\n if (/^-?[\\d.]+$/.test(number)) return `${number}${unit}`;\n return number;\n}\n\n/**\n * 获取数字的小数位数\n * @param num - 需要计算小数位数的数字或数字字符串\n * @returns 返回数字的小数位数,如果是整数则返回0\n * @example\n * // 基本用法\n * numberDecimals(3.1415); // 4\n * numberDecimals(\"3.1415\"); // 4\n * numberDecimals(100); // 0\n * numberDecimals(\"100\"); // 0\n * // 科学计数法\n * numberDecimals(\"1.23e-4\"); // 6\n */\nexport function numberDecimals(num: number | string) {\n const numStr = String(num);\n const matches = numStr.match(/(?:\\.(\\d+))?(?:e-(\\d+))?$/i);\n if (!matches) return 0;\n return (matches[1] || '').length + Number.parseInt(matches[2] || '0');\n}\n","import { numberConvert, randomNumber } from './number';\nimport { isFunction, isNullish, isNumber, isObject, isString, isUndefined } from './type';\n\n/** 阿拉伯数字字符集合 */\nexport const STRING_ARABIC_NUMERALS = '0123456789';\n/** 十六进制字符集合 */\nexport const STRING_HEXADECIMALS = '0123456789abcdef';\n/** 小写字母字符集合 */\nexport const STRING_LOWERCASE_ALPHA = 'abcdefghijklmnopqrstuvwxyz';\n/** 大写字母字符集合 */\nexport const STRING_UPPERCASE_ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\n/** 随机字符串字典,包含数字、大写字母和小写字母 */\nexport const STRING_DICT = `${STRING_ARABIC_NUMERALS + STRING_UPPERCASE_ALPHA + STRING_LOWERCASE_ALPHA}`;\n\n/**\n * 将字符串转换为驼峰格式\n * @param {string} string - 要转换的字符串\n * @param {boolean} [bigger] - 是否大写第一个字母,默认为 false\n * @returns {string} - 转换后的驼峰格式字符串\n */\nexport function stringCamelCase(string: string, bigger?: boolean): string {\n const string2 = string.replace(/[\\s_-](.)/g, (_, char) => (char as string).toUpperCase());\n return bigger ? string2.slice(0, 1).toUpperCase() + string2.slice(1) : string2;\n}\n\n/**\n * 将字符串转换为连字格式\n * @param {string} string - 要转换的字符串\n * @param {string} [separator] - 分隔符,默认是 \"-\"(短横线)\n * @returns {string} - 转换后的连字格式字符串\n */\nexport function stringKebabCase(string: string, separator = '-'): string {\n return string.replace(/[A-Z]/g, (origin) => `${separator}${origin.toLowerCase()}`);\n}\n\n/**\n * 生成随机字符串\n * @param {number} length - 生成的随机字符串长度\n * @param {string} [dict] - 用于生成随机字符串的字符字典,默认为数字、小写字母和大写字母的组合\n * @returns {string} - 生成的随机字符串\n * @example\n * randomString(10); // 生成一个长度为 10 的随机字符串\n * randomString(8, 'ABCDEF'); // 生成一个长度为 8 的随机字符串,仅包含字符 'ABCDEF'\n */\nexport function randomString(length: number, dict?: string): string {\n const dictFinal = dict || STRING_DICT;\n const dictLength = dictFinal.length;\n\n let result = '';\n\n for (let i = 0; i < length; i++) {\n result += dictFinal.charAt(randomNumber(0, dictLength - 1));\n }\n\n return result;\n}\n\n/**\n * 简单的模板引擎,类似于 Python 的 `.format()` 方法\n * 支持通过索引或对象/名称的方式传递变量\n * 当使用对象/名称方式时,可以传递一个回退值作为第三个参数\n *\n * @category 字符串\n * @example\n * ```\n * // 索引方式\n * const result = stringFormat(\n * '你好 {0}!我的名字是 {1}。',\n * '张三',\n * '李四'\n * ); // 你好 张三!我的名字是 李四。\n * ```\n *\n * @example\n * ```\n * // 对象方式\n * const result = stringFormat(\n * '{greet}!我的名字是 {name}。',\n * { greet: '你好', name: '王五' }\n * ); // 你好!我的名字是 王五。\n * ```\n *\n * @example\n * ```\n * // 带回退值的对象方式\n * const result = stringFormat(\n * '{greet}!我的名字是 {name}。',\n * { greet: '你好' }, // name 未传递,因此会使用回退值\n * '未知'\n * ); // 你好!我的名字是 未知。\n * ```\n */\nexport function stringFormat(\n str: string,\n object: Record<string | number, unknown>,\n fallback?: string | ((key: string) => string),\n): string;\nexport function stringFormat(str: string, ...args: (string | number | bigint | undefined | null)[]): string;\nexport function stringFormat(str: string, ...args: unknown[]): string {\n const [firstArg, fallback] = args;\n\n if (isObject(firstArg) || isUndefined(firstArg)) {\n const vars = firstArg || {};\n return str.replace(/\\{(\\w+)\\}/g, (_, key) => vars[key] ?? (isFunction(fallback) ? fallback(key) : fallback) ?? key);\n }\n\n return str.replace(/\\{(\\d+)\\}/g, (_, key) => {\n const index = Number(key);\n if (Number.isNaN(index)) return key;\n return args[index];\n });\n}\n\n/**\n * 生成符合 [RFC 4122](https://www.ietf.org/rfc/rfc4122.txt) 版本 4 的 UUID 字符串\n * @returns {string} - 生成的 UUID 字符串\n * @example\n * const uuid = randomUUID4();\n * console.log(uuid); // 输出类似 '123e4567-e89b-12d3-a456-426614174000' 的 UUID 字符串\n */\nexport function randomUUID4(): string {\n const template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';\n let result = '';\n\n for (let i = 0; i < template.length; i++) {\n const t = template[i];\n\n if (t === '-' || t === '4') {\n result += t;\n continue;\n }\n\n if (t === 'y') {\n result += randomString(1, '89ab');\n continue;\n }\n\n result += randomString(1, STRING_HEXADECIMALS);\n }\n\n return result;\n}\n\n/**\n * 将值转换为字符串,若值为 null 或 undefined 则返回空字符串\n * @param {unknown} value - 需要转换的值\n * @returns {string} 转换后的字符串结果\n */\nexport function stringify(value: unknown) {\n return isNullish(value) ? '' : String(value);\n}\n"],"names":["objectDefaults","isNumber","isObject","isUndefined","isFunction","isNullish"],"mappings":"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"}
|
package/dist/string2.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"string2.mjs","sources":["../src/number.ts","../src/string.ts"],"sourcesContent":["import { objectDefaults } from './object';\nimport { STRING_DICT } from './string';\nimport { isNumber } from './type';\n\nexport type NumberFixedOptions = {\n /**\n * 保留的小数位数\n * @default 0\n */\n decimals?: number;\n\n /**\n * 舍入方法,0 为四舍五入,1 为向上取整,-1 为向下取整\n * @default 0\n */\n round?: 0 | 1 | -1;\n};\n\n/**\n * 对数字进行精确小数位数处理并按规则舍入\n * @param number 需要处理的原始数值\n * @param options 可选配置参数\n * @returns 处理后的数值(number类型)\n * @example\n * // 四舍五入示例\n * numberFixed(3.1415, { decimals: 2 }); // 3.14\n * // 向上取整示例\n * numberFixed(3.1415, { decimals: 2, round: 1 }); // 3.15\n * // 向下取整示例\n * numberFixed(3.9999, { decimals: 1, round: -1 }); // 3.9\n */\nexport function numberFixed(number: number, options?: NumberFixedOptions) {\n const { decimals = 0, round = 0 } = options || {};\n const scale = 10 ** decimals;\n\n if (round === 1) {\n return Math.ceil(number * scale) / scale;\n }\n\n if (round === -1) {\n return Math.floor(number * scale) / scale;\n }\n\n return Math.round(number * scale) / scale;\n}\n\n/**\n * 生成指定范围内的随机数\n * @param {number | string} min - 随机数的最小值(包含,支持小数、字符串)\n * @param {number | string} max - 随机数的最大值(包含,支持小数、字符串)\n * @returns {number} - 生成的随机数\n * @example\n * // 生成 1 到 10 之间的随机整数\n * randomNumber(1, 10); // 可能返回 7\n *\n * // 生成 0.1 到 2 之间的一位随机小数\n * randomNumber(0.1, 2); // 可能返回 0.7\n *\n * // 生成 0.10 到 2 之间的两位随机小数\n * randomNumber(\"0.10\", 2); // 可能返回 0.75\n */\nexport function randomNumber(min: number | string, max: number | string): number {\n const minDecimals = numberDecimals(min);\n const maxDecimals = numberDecimals(max);\n const decimals = Math.max(minDecimals, maxDecimals);\n const scale = 10 ** decimals;\n\n const minNum = Number(min);\n const maxNum = Number(max);\n const [minFinal, maxFinal] = minNum > maxNum ? [maxNum, minNum] : [minNum, maxNum];\n\n const scaledMin = minFinal * scale;\n const scaledMax = maxFinal * scale;\n\n return Math.floor(Math.random() * (scaledMax - scaledMin + 1) + scaledMin) / scale;\n}\n\n/**\n * 数字缩写选项\n */\nexport type NumberAbbrOptions = {\n /**\n * 进制基数,用于计算单位进阶(如 1000 表示千进制)\n * @default 1000\n */\n base?: number;\n\n /**\n * 数值保留的小数位数\n * @default 0\n */\n decimals?: number;\n};\n\n/**\n * 将数字转换为带单位缩写的字符串表示\n *\n * @param {number} number - 需要转换的原始数值\n * @param {Array<string>} units - 单位数组,按从小到大顺序排列(如['B','KB','MB']),不能为空\n * @param {NumberAbbrOptions} [options] - 可选配置参数\n * @returns {string} - 转换后的带单位字符串(如\"1.2KB\")\n * @example\n * // 基础用法\n * numberAbbr(1500, ['', 'K', 'M'], { base: 1000 }); // \"1.5K\"\n * @example\n * // 自定义小数位\n * numberAbbr(123456, ['B','KB','MB'], { decimals: 1 }); // \"0.1MB\"\n * @example\n * // 处理不足基数的情况\n * numberAbbr(500, ['B','KB']); // \"500B\"\n */\nexport function numberAbbr(number: number, units: Array<string>, options?: NumberAbbrOptions): string {\n const { base = 1000, decimals = 0 } = options || {};\n const { length } = units;\n\n if (length === 0) throw new Error('数字单位组不能为空');\n\n let numberFinal = number;\n let step = 0;\n\n while (numberFinal >= base && step < length - 1) {\n numberFinal = numberFinal / base;\n step++;\n }\n\n const value = numberFixed(numberFinal, { decimals: decimals, round: -1 });\n const unit = units[step];\n\n return `${value}${unit}`;\n}\n\n/**\n * 将文件大小转换为带单位缩写的字符串表示\n *\n * @param {number} number - 需要转换的文件大小数值\n * @param {number} [decimals=0] - 数值保留的小数位数\n * @returns {string} - 转换后的带单位字符串(如\"1.2KB\")\n * @example\n * // 基础用法\n * fileSizeAbbr(1024); // \"1KB\"\n * @example\n * // 自定义小数位\n * fileSizeAbbr(123456, 1); // \"0.1MB\"\n */\nexport function fileSizeAbbr(number: number, decimals = 0) {\n return numberAbbr(number, ['B', 'KB', 'MB', 'GB', 'TB'], {\n base: 1024,\n decimals: decimals,\n });\n}\n\n/**\n * 将十进制数转换为指定进制的字符串表示\n *\n * @param {number | bigint} decimal - 需要转换的十进制数,可以是任意长度的数字或大整数\n * @param {string} [dict] - 用于表示进制的字符字典,默认为数字、小写字母和大写字母的组合(62 进制)\n * @returns {string} - 转换后的指定进制字符串\n * @throws {Error} - 如果字符字典的长度小于 2,将抛出错误\n * @example\n * // 默认 62 进制\n * numberConvert(123456789); // \"8M0kX\"\n * @example\n * // 自定义 16 进制\n * numberConvert(255, '0123456789ABCDEF'); // \"FF\"\n * @example\n * // 处理大整数\n * numberConvert(9007199254740991n); // \"2gosa7pa2GV\"\n */\nexport function numberConvert(decimal: number | bigint, dict?: string): string {\n const dictFinal = dict || STRING_DICT;\n\n if (dictFinal.length < 2) throw new Error('进制转换字典长度不能小于 2');\n\n let bigInt = BigInt(decimal);\n const symbol = bigInt < 0n ? '-' : '';\n bigInt = bigInt < 0n ? -bigInt : bigInt;\n const result: Array<string> = [];\n const { length } = dictFinal;\n const bigLength = BigInt(length);\n const calculate = (): void => {\n const y = Number(bigInt % bigLength);\n\n bigInt = bigInt / bigLength;\n result.unshift(dictFinal[y]);\n\n if (bigInt > 0) {\n calculate();\n }\n };\n\n calculate();\n\n return symbol + result.join('');\n}\n\n/**\n * 数字格式化配置选项\n */\nexport type NumberFormatOptions = {\n /**\n * 分隔符字符,用于数字分隔\n * @default ','\n * @example 使用 '_' 分隔符时,123456 会格式化为 '123_456'\n */\n separator?: string;\n\n /**\n * 分隔步长,即每隔多少位添加分隔符\n * @default 3\n * @example 步长为 2 时,123456 会格式化为 '12,34,56'\n */\n step?: number;\n};\n\n/**\n * 数字格式化\n * @param [number] {number} 数字\n * @param options {NumberFormatOptions} 格式化配置\n * @returns {string} 分割后的字符串\n * @example\n * // 使用默认分隔符和步长\n * numberFormat(123456.789); // => \"123,456.789\"\n * // 自定义分隔符\n * numberFormat(123456.789, '_'); // => \"123_456.789\"\n * // 自定义步长\n * numberFormat(123456.789, 2); // => \"12,34,56.789\"\n * // 使用对象配置\n * numberFormat(123456.789, { separator: '.', step: 4 }); // => \"12.3456.789\"\n */\nexport function numberFormat(number: number, options: NumberFormatOptions): string;\nexport function numberFormat(number: number, separator: string): string;\nexport function numberFormat(number: number, step: number): string;\nexport function numberFormat(number: number): string;\nexport function numberFormat(number: number, options?: NumberFormatOptions | string | number) {\n let optionsFinal: Required<NumberFormatOptions> = {\n separator: ',',\n step: 3,\n };\n\n if (typeof options === 'string') {\n optionsFinal.separator = options;\n } else if (typeof options === 'number') {\n optionsFinal.step = options;\n } else {\n optionsFinal = objectDefaults(options || {}, optionsFinal) as Required<NumberFormatOptions>;\n }\n\n const { separator, step } = optionsFinal;\n const arr = String(number).split('.');\n const re = new RegExp(`(\\\\d)(?=(\\\\d{${step}})+(?!\\\\d))`, 'g');\n const p1 = arr[0].replace(re, `$1${separator}`);\n\n return p1 + (arr[1] ? `.${arr[1]}` : '');\n}\n\n/**\n * 将数字限制在指定范围内。\n *\n * @param min - 最小值。\n * @param number - 要限制的数字。\n * @param max - 最大值。\n * @returns 限制后的数字。\n */\nexport function numberClamp(min: number, number: number, max: number) {\n return Math.min(Math.max(number, min), max);\n}\n\n/**\n * 为数字添加单位\n * @param number - 需要处理的数字,可以是数字类型或字符串类型\n * @param unit - 要添加的单位,默认为空字符串\n * @returns 如果输入是数字或纯数字字符串,则返回带单位的字符串;否则返回原值\n */\nexport function numberUnit(number: string | number, unit = '') {\n if (isNumber(number)) return `${number}${unit}`;\n if (/^-?[\\d.]+$/.test(number)) return `${number}${unit}`;\n return number;\n}\n\n/**\n * 获取数字的小数位数\n * @param num - 需要计算小数位数的数字或数字字符串\n * @returns 返回数字的小数位数,如果是整数则返回0\n * @example\n * // 基本用法\n * numberDecimals(3.1415); // 4\n * numberDecimals(\"3.1415\"); // 4\n * numberDecimals(100); // 0\n * numberDecimals(\"100\"); // 0\n * // 科学计数法\n * numberDecimals(\"1.23e-4\"); // 6\n */\nexport function numberDecimals(num: number | string) {\n const numStr = String(num);\n const matches = numStr.match(/(?:\\.(\\d+))?(?:e-(\\d+))?$/i);\n if (!matches) return 0;\n return (matches[1] || '').length + Number.parseInt(matches[2] || '0');\n}\n","import { numberConvert, randomNumber } from './number';\nimport { isFunction, isNullish, isNumber, isObject, isString, isUndefined } from './type';\n\n/** 阿拉伯数字字符集合 */\nexport const STRING_ARABIC_NUMERALS = '0123456789';\n/** 十六进制字符集合 */\nexport const STRING_HEXADECIMALS = '0123456789abcdef';\n/** 小写字母字符集合 */\nexport const STRING_LOWERCASE_ALPHA = 'abcdefghijklmnopqrstuvwxyz';\n/** 大写字母字符集合 */\nexport const STRING_UPPERCASE_ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\n/** 随机字符串字典,包含数字、大写字母和小写字母 */\nexport const STRING_DICT = `${STRING_ARABIC_NUMERALS + STRING_UPPERCASE_ALPHA + STRING_LOWERCASE_ALPHA}`;\n\n/**\n * 将字符串转换为驼峰格式\n * @param {string} string - 要转换的字符串\n * @param {boolean} [bigger] - 是否大写第一个字母,默认为 false\n * @returns {string} - 转换后的驼峰格式字符串\n */\nexport function stringCamelCase(string: string, bigger?: boolean): string {\n const string2 = string.replace(/[\\s_-](.)/g, (_, char) => (char as string).toUpperCase());\n return bigger ? string2.slice(0, 1).toUpperCase() + string2.slice(1) : string2;\n}\n\n/**\n * 将字符串转换为连字格式\n * @param {string} string - 要转换的字符串\n * @param {string} [separator] - 分隔符,默认是 \"-\"(短横线)\n * @returns {string} - 转换后的连字格式字符串\n */\nexport function stringKebabCase(string: string, separator = '-'): string {\n return string.replace(/[A-Z]/g, (origin) => `${separator}${origin.toLowerCase()}`);\n}\n\n/**\n * 生成随机字符串\n * @param {number} length - 生成的随机字符串长度\n * @param {string} [dict] - 用于生成随机字符串的字符字典,默认为数字、小写字母和大写字母的组合\n * @returns {string} - 生成的随机字符串\n * @example\n * randomString(10); // 生成一个长度为 10 的随机字符串\n * randomString(8, 'ABCDEF'); // 生成一个长度为 8 的随机字符串,仅包含字符 'ABCDEF'\n */\nexport function randomString(length: number, dict?: string): string {\n const dictFinal = dict || STRING_DICT;\n const dictLength = dictFinal.length;\n\n let result = '';\n\n for (let i = 0; i < length; i++) {\n result += dictFinal.charAt(randomNumber(0, dictLength - 1));\n }\n\n return result;\n}\n\n/**\n * 简单的模板引擎,类似于 Python 的 `.format()` 方法\n * 支持通过索引或对象/名称的方式传递变量\n * 当使用对象/名称方式时,可以传递一个回退值作为第三个参数\n *\n * @category 字符串\n * @example\n * ```\n * // 索引方式\n * const result = stringFormat(\n * '你好 {0}!我的名字是 {1}。',\n * '张三',\n * '李四'\n * ); // 你好 张三!我的名字是 李四。\n * ```\n *\n * @example\n * ```\n * // 对象方式\n * const result = stringFormat(\n * '{greet}!我的名字是 {name}。',\n * { greet: '你好', name: '王五' }\n * ); // 你好!我的名字是 王五。\n * ```\n *\n * @example\n * ```\n * // 带回退值的对象方式\n * const result = stringFormat(\n * '{greet}!我的名字是 {name}。',\n * { greet: '你好' }, // name 未传递,因此会使用回退值\n * '未知'\n * ); // 你好!我的名字是 未知。\n * ```\n */\nexport function stringFormat(\n str: string,\n object: Record<string | number, unknown>,\n fallback?: string | ((key: string) => string),\n): string;\nexport function stringFormat(str: string, ...args: (string | number | bigint | undefined | null)[]): string;\nexport function stringFormat(str: string, ...args: unknown[]): string {\n const [firstArg, fallback] = args;\n\n if (isObject(firstArg) || isUndefined(firstArg)) {\n const vars = firstArg || {};\n return str.replace(/\\{(\\w+)\\}/g, (_, key) => vars[key] ?? (isFunction(fallback) ? fallback(key) : fallback) ?? key);\n }\n\n return str.replace(/\\{(\\d+)\\}/g, (_, key) => {\n const index = Number(key);\n if (Number.isNaN(index)) return key;\n return args[index];\n });\n}\n\n/**\n * 生成符合 [RFC 4122](https://www.ietf.org/rfc/rfc4122.txt) 版本 4 的 UUID 字符串\n * @returns {string} - 生成的 UUID 字符串\n * @example\n * const uuid = randomUUID4();\n * console.log(uuid); // 输出类似 '123e4567-e89b-12d3-a456-426614174000' 的 UUID 字符串\n */\nexport function randomUUID4(): string {\n const template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';\n let result = '';\n\n for (let i = 0; i < template.length; i++) {\n const t = template[i];\n\n if (t === '-' || t === '4') {\n result += t;\n continue;\n }\n\n if (t === 'y') {\n result += randomString(1, '89ab');\n continue;\n }\n\n result += randomString(1, STRING_HEXADECIMALS);\n }\n\n return result;\n}\n\n/**\n * 将值转换为字符串,若值为 null 或 undefined 则返回空字符串\n * @param {unknown} value - 需要转换的值\n * @returns {string} 转换后的字符串结果\n */\nexport function stringify(value: unknown) {\n return isNullish(value) ? '' : String(value);\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"string2.mjs","sources":["../src/number.ts","../src/string.ts"],"sourcesContent":["import { objectDefaults } from './object';\nimport { STRING_DICT } from './string';\nimport { isNumber } from './type';\n\nexport type NumberFixedOptions = {\n /**\n * 保留的小数位数\n * @default 0\n */\n decimals?: number;\n\n /**\n * 舍入方法,0 为四舍五入,1 为向上取整,-1 为向下取整\n * @default 0\n */\n round?: 0 | 1 | -1;\n};\n\n/**\n * 对数字进行精确小数位数处理并按规则舍入\n * @param number 需要处理的原始数值\n * @param options 可选配置参数\n * @returns 处理后的数值(number类型)\n * @example\n * // 四舍五入示例\n * numberFixed(3.1415, { decimals: 2 }); // 3.14\n * // 向上取整示例\n * numberFixed(3.1415, { decimals: 2, round: 1 }); // 3.15\n * // 向下取整示例\n * numberFixed(3.9999, { decimals: 1, round: -1 }); // 3.9\n */\nexport function numberFixed(number: number, options?: NumberFixedOptions) {\n const { decimals = 0, round = 0 } = options || {};\n const scale = 10 ** decimals;\n\n if (round === 1) {\n return Math.ceil(number * scale) / scale;\n }\n\n if (round === -1) {\n return Math.floor(number * scale) / scale;\n }\n\n return Math.round(number * scale) / scale;\n}\n\n/**\n * 生成指定范围内的随机数\n * @param {number | string} min - 随机数的最小值(包含,支持小数、字符串)\n * @param {number | string} max - 随机数的最大值(包含,支持小数、字符串)\n * @returns {number} - 生成的随机数\n * @example\n * // 生成 1 到 10 之间的随机整数\n * randomNumber(1, 10); // 可能返回 7\n *\n * // 生成 0.1 到 2 之间的一位随机小数\n * randomNumber(0.1, 2); // 可能返回 0.7\n *\n * // 生成 0.10 到 2 之间的两位随机小数\n * randomNumber(\"0.10\", 2); // 可能返回 0.75\n */\nexport function randomNumber(min: number | string, max: number | string): number {\n const minDecimals = numberDecimals(min);\n const maxDecimals = numberDecimals(max);\n const decimals = Math.max(minDecimals, maxDecimals);\n const scale = 10 ** decimals;\n\n const minNum = Number(min);\n const maxNum = Number(max);\n const [minFinal, maxFinal] = minNum > maxNum ? [maxNum, minNum] : [minNum, maxNum];\n\n const scaledMin = minFinal * scale;\n const scaledMax = maxFinal * scale;\n\n return Math.floor(Math.random() * (scaledMax - scaledMin + 1) + scaledMin) / scale;\n}\n\n/**\n * 数字缩写选项\n */\nexport type NumberAbbrOptions = {\n /**\n * 进制基数,用于计算单位进阶(如 1000 表示千进制)\n * @default 1000\n */\n base?: number;\n\n /**\n * 数值保留的小数位数\n * @default 0\n */\n decimals?: number;\n};\n\n/**\n * 将数字转换为带单位缩写的字符串表示\n *\n * @param {number} number - 需要转换的原始数值\n * @param {Array<string>} units - 单位数组,按从小到大顺序排列(如['B','KB','MB']),不能为空\n * @param {NumberAbbrOptions} [options] - 可选配置参数\n * @returns {string} - 转换后的带单位字符串(如\"1.2KB\")\n * @example\n * // 基础用法\n * numberAbbr(1500, ['', 'K', 'M'], { base: 1000 }); // \"1.5K\"\n * @example\n * // 自定义小数位\n * numberAbbr(123456, ['B','KB','MB'], { decimals: 1 }); // \"0.1MB\"\n * @example\n * // 处理不足基数的情况\n * numberAbbr(500, ['B','KB']); // \"500B\"\n */\nexport function numberAbbr(number: number, units: Array<string>, options?: NumberAbbrOptions): string {\n const { base = 1000, decimals = 0 } = options || {};\n const { length } = units;\n\n if (length === 0) throw new Error('数字单位组不能为空');\n\n let numberFinal = number;\n let step = 0;\n\n while (numberFinal >= base && step < length - 1) {\n numberFinal = numberFinal / base;\n step++;\n }\n\n const value = numberFixed(numberFinal, { decimals: decimals, round: -1 });\n const unit = units[step];\n\n return `${value}${unit}`;\n}\n\n/**\n * 将文件大小转换为带单位缩写的字符串表示\n *\n * @param {number} number - 需要转换的文件大小数值\n * @param {number} [decimals=0] - 数值保留的小数位数\n * @returns {string} - 转换后的带单位字符串(如\"1.2KB\")\n * @example\n * // 基础用法\n * fileSizeAbbr(1024); // \"1KB\"\n * @example\n * // 自定义小数位\n * fileSizeAbbr(123456, 1); // \"0.1MB\"\n */\nexport function fileSizeAbbr(number: number, decimals = 0) {\n return numberAbbr(number, ['B', 'KB', 'MB', 'GB', 'TB'], {\n base: 1024,\n decimals: decimals,\n });\n}\n\n/**\n * 将十进制数转换为指定进制的字符串表示\n *\n * @param {number | bigint} decimal - 需要转换的十进制数,可以是任意长度的数字或大整数\n * @param {string} [dict] - 用于表示进制的字符字典,默认为数字、小写字母和大写字母的组合(62 进制)\n * @returns {string} - 转换后的指定进制字符串\n * @throws {Error} - 如果字符字典的长度小于 2,将抛出错误\n * @example\n * // 默认 62 进制\n * numberConvert(123456789); // \"8M0kX\"\n * @example\n * // 自定义 16 进制\n * numberConvert(255, '0123456789ABCDEF'); // \"FF\"\n * @example\n * // 处理大整数\n * numberConvert(9007199254740991n); // \"2gosa7pa2GV\"\n */\nexport function numberConvert(decimal: number | bigint, dict?: string): string {\n const dictFinal = dict || STRING_DICT;\n\n if (dictFinal.length < 2) throw new Error('进制转换字典长度不能小于 2');\n\n let bigInt = BigInt(decimal);\n const symbol = bigInt < 0n ? '-' : '';\n bigInt = bigInt < 0n ? -bigInt : bigInt;\n const result: Array<string> = [];\n const { length } = dictFinal;\n const bigLength = BigInt(length);\n const calculate = (): void => {\n const y = Number(bigInt % bigLength);\n\n bigInt = bigInt / bigLength;\n result.unshift(dictFinal[y]);\n\n if (bigInt > 0) {\n calculate();\n }\n };\n\n calculate();\n\n return symbol + result.join('');\n}\n\n/**\n * 数字格式化配置选项\n */\nexport type NumberFormatOptions = {\n /**\n * 分隔符字符,用于数字分隔\n * @default ','\n * @example 使用 '_' 分隔符时,123456 会格式化为 '123_456'\n */\n separator?: string;\n\n /**\n * 分隔步长,即每隔多少位添加分隔符\n * @default 3\n * @example 步长为 2 时,123456 会格式化为 '12,34,56'\n */\n step?: number;\n};\n\n/**\n * 数字格式化\n * @param [number] {number} 数字\n * @param options {NumberFormatOptions} 格式化配置\n * @returns {string} 分割后的字符串\n * @example\n * // 使用默认分隔符和步长\n * numberFormat(123456.789); // => \"123,456.789\"\n * // 自定义分隔符\n * numberFormat(123456.789, '_'); // => \"123_456.789\"\n * // 自定义步长\n * numberFormat(123456.789, 2); // => \"12,34,56.789\"\n * // 使用对象配置\n * numberFormat(123456.789, { separator: '.', step: 4 }); // => \"12.3456.789\"\n */\nexport function numberFormat(number: number | string, options: NumberFormatOptions): string;\nexport function numberFormat(number: number | string, separator: string): string;\nexport function numberFormat(number: number | string, step: number): string;\nexport function numberFormat(number: number | string): string;\nexport function numberFormat(number: number | string, options?: NumberFormatOptions | string | number) {\n let optionsFinal: Required<NumberFormatOptions> = {\n separator: ',',\n step: 3,\n };\n\n if (typeof options === 'string') {\n optionsFinal.separator = options;\n } else if (typeof options === 'number') {\n optionsFinal.step = options;\n } else {\n optionsFinal = objectDefaults(options || {}, optionsFinal) as Required<NumberFormatOptions>;\n }\n\n const { separator, step } = optionsFinal;\n const arr = String(number).split('.');\n const re = new RegExp(`(\\\\d)(?=(\\\\d{${step}})+(?!\\\\d))`, 'g');\n const p1 = arr[0].replace(re, `$1${separator}`);\n\n return p1 + (arr[1] ? `.${arr[1]}` : '');\n}\n\n/**\n * 将数字限制在指定范围内。\n *\n * @param min - 最小值。\n * @param number - 要限制的数字。\n * @param max - 最大值。\n * @returns 限制后的数字。\n */\nexport function numberClamp(min: number, number: number, max: number) {\n return Math.min(Math.max(number, min), max);\n}\n\n/**\n * 为数字添加单位\n * @param number - 需要处理的数字,可以是数字类型或字符串类型\n * @param unit - 要添加的单位,默认为空字符串\n * @returns 如果输入是数字或纯数字字符串,则返回带单位的字符串;否则返回原值\n */\nexport function numberUnit(number: string | number, unit = '') {\n if (isNumber(number)) return `${number}${unit}`;\n if (/^-?[\\d.]+$/.test(number)) return `${number}${unit}`;\n return number;\n}\n\n/**\n * 获取数字的小数位数\n * @param num - 需要计算小数位数的数字或数字字符串\n * @returns 返回数字的小数位数,如果是整数则返回0\n * @example\n * // 基本用法\n * numberDecimals(3.1415); // 4\n * numberDecimals(\"3.1415\"); // 4\n * numberDecimals(100); // 0\n * numberDecimals(\"100\"); // 0\n * // 科学计数法\n * numberDecimals(\"1.23e-4\"); // 6\n */\nexport function numberDecimals(num: number | string) {\n const numStr = String(num);\n const matches = numStr.match(/(?:\\.(\\d+))?(?:e-(\\d+))?$/i);\n if (!matches) return 0;\n return (matches[1] || '').length + Number.parseInt(matches[2] || '0');\n}\n","import { numberConvert, randomNumber } from './number';\nimport { isFunction, isNullish, isNumber, isObject, isString, isUndefined } from './type';\n\n/** 阿拉伯数字字符集合 */\nexport const STRING_ARABIC_NUMERALS = '0123456789';\n/** 十六进制字符集合 */\nexport const STRING_HEXADECIMALS = '0123456789abcdef';\n/** 小写字母字符集合 */\nexport const STRING_LOWERCASE_ALPHA = 'abcdefghijklmnopqrstuvwxyz';\n/** 大写字母字符集合 */\nexport const STRING_UPPERCASE_ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\n/** 随机字符串字典,包含数字、大写字母和小写字母 */\nexport const STRING_DICT = `${STRING_ARABIC_NUMERALS + STRING_UPPERCASE_ALPHA + STRING_LOWERCASE_ALPHA}`;\n\n/**\n * 将字符串转换为驼峰格式\n * @param {string} string - 要转换的字符串\n * @param {boolean} [bigger] - 是否大写第一个字母,默认为 false\n * @returns {string} - 转换后的驼峰格式字符串\n */\nexport function stringCamelCase(string: string, bigger?: boolean): string {\n const string2 = string.replace(/[\\s_-](.)/g, (_, char) => (char as string).toUpperCase());\n return bigger ? string2.slice(0, 1).toUpperCase() + string2.slice(1) : string2;\n}\n\n/**\n * 将字符串转换为连字格式\n * @param {string} string - 要转换的字符串\n * @param {string} [separator] - 分隔符,默认是 \"-\"(短横线)\n * @returns {string} - 转换后的连字格式字符串\n */\nexport function stringKebabCase(string: string, separator = '-'): string {\n return string.replace(/[A-Z]/g, (origin) => `${separator}${origin.toLowerCase()}`);\n}\n\n/**\n * 生成随机字符串\n * @param {number} length - 生成的随机字符串长度\n * @param {string} [dict] - 用于生成随机字符串的字符字典,默认为数字、小写字母和大写字母的组合\n * @returns {string} - 生成的随机字符串\n * @example\n * randomString(10); // 生成一个长度为 10 的随机字符串\n * randomString(8, 'ABCDEF'); // 生成一个长度为 8 的随机字符串,仅包含字符 'ABCDEF'\n */\nexport function randomString(length: number, dict?: string): string {\n const dictFinal = dict || STRING_DICT;\n const dictLength = dictFinal.length;\n\n let result = '';\n\n for (let i = 0; i < length; i++) {\n result += dictFinal.charAt(randomNumber(0, dictLength - 1));\n }\n\n return result;\n}\n\n/**\n * 简单的模板引擎,类似于 Python 的 `.format()` 方法\n * 支持通过索引或对象/名称的方式传递变量\n * 当使用对象/名称方式时,可以传递一个回退值作为第三个参数\n *\n * @category 字符串\n * @example\n * ```\n * // 索引方式\n * const result = stringFormat(\n * '你好 {0}!我的名字是 {1}。',\n * '张三',\n * '李四'\n * ); // 你好 张三!我的名字是 李四。\n * ```\n *\n * @example\n * ```\n * // 对象方式\n * const result = stringFormat(\n * '{greet}!我的名字是 {name}。',\n * { greet: '你好', name: '王五' }\n * ); // 你好!我的名字是 王五。\n * ```\n *\n * @example\n * ```\n * // 带回退值的对象方式\n * const result = stringFormat(\n * '{greet}!我的名字是 {name}。',\n * { greet: '你好' }, // name 未传递,因此会使用回退值\n * '未知'\n * ); // 你好!我的名字是 未知。\n * ```\n */\nexport function stringFormat(\n str: string,\n object: Record<string | number, unknown>,\n fallback?: string | ((key: string) => string),\n): string;\nexport function stringFormat(str: string, ...args: (string | number | bigint | undefined | null)[]): string;\nexport function stringFormat(str: string, ...args: unknown[]): string {\n const [firstArg, fallback] = args;\n\n if (isObject(firstArg) || isUndefined(firstArg)) {\n const vars = firstArg || {};\n return str.replace(/\\{(\\w+)\\}/g, (_, key) => vars[key] ?? (isFunction(fallback) ? fallback(key) : fallback) ?? key);\n }\n\n return str.replace(/\\{(\\d+)\\}/g, (_, key) => {\n const index = Number(key);\n if (Number.isNaN(index)) return key;\n return args[index];\n });\n}\n\n/**\n * 生成符合 [RFC 4122](https://www.ietf.org/rfc/rfc4122.txt) 版本 4 的 UUID 字符串\n * @returns {string} - 生成的 UUID 字符串\n * @example\n * const uuid = randomUUID4();\n * console.log(uuid); // 输出类似 '123e4567-e89b-12d3-a456-426614174000' 的 UUID 字符串\n */\nexport function randomUUID4(): string {\n const template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';\n let result = '';\n\n for (let i = 0; i < template.length; i++) {\n const t = template[i];\n\n if (t === '-' || t === '4') {\n result += t;\n continue;\n }\n\n if (t === 'y') {\n result += randomString(1, '89ab');\n continue;\n }\n\n result += randomString(1, STRING_HEXADECIMALS);\n }\n\n return result;\n}\n\n/**\n * 将值转换为字符串,若值为 null 或 undefined 则返回空字符串\n * @param {unknown} value - 需要转换的值\n * @returns {string} 转换后的字符串结果\n */\nexport function stringify(value: unknown) {\n return isNullish(value) ? '' : String(value);\n}\n"],"names":[],"mappings":"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"}
|