Skip to content

Commit

Permalink
feat: 首字母转大小写方法
Browse files Browse the repository at this point in the history
  • Loading branch information
D-xuanmo committed Oct 27, 2024
1 parent 6156124 commit 51b42ba
Show file tree
Hide file tree
Showing 13 changed files with 316 additions and 120 deletions.
19 changes: 0 additions & 19 deletions .prettierrc

This file was deleted.

64 changes: 32 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,38 @@ import { debounce } from '@xuanmo/utils'

### 已有方法

| 工具名 | 描述 | Nodejs 可用 |
|:--------------------:|:----------------------------:|:---------:|
| realType | 获取数据真实类型 ||
| isObject | 是否为对象 ||
| isRegexp | 是否为正则表达式 ||
| isFunction | 是否为函数 ||
| isImageUrl | 判断 url 是否为图片路径 ||
| isNumber | 是否为纯数字 ||
| isEmpty | 是否为空 ||
| isBoolean | 是否为布尔值 ||
| isPromise | 是否为 `Promise` ||
| toBoolean | 转换 `string` 布尔值 ||
| toLowerCamelCase | 下划线转小驼峰 ||
| toUnderline | 小驼峰转下划线分割 ||
| toPascalCase | 中横线转大驼峰 ||
| formatThousandth | 数字千分位 ||
| countDown | 倒计时 ||
| debounce | 防抖 ||
| debounceDecorator | 防抖装饰器版 ||
| deepCopy | 深拷贝 ||
| searchParams | 获取 URL 单个查询参数 ||
| formatQueryParams | 获取 URL 全部查询参数 ||
| createRandomID | 生成随机 ID ||
| objectKeyToCamelCase | Object key 转换为小驼峰 ||
| ua |`navigator.userAgent` 进行解析 ||
| dCookie | `cookie` 操作 ||
| generateTree | 一维数组转树形数据 ||
| throwError | 统一报错信息处理 ||
| debugWarn | 警告信息统一处理 ||
| deleteArrayItems | 指定删除数组的某些元素 ||
| pickLastItem | 选择数组的最后一项元素 ||
| treeToMap | 树形数据转 map ||
|工具名|描述|Nodejs 可用|
|:----:|:---:|:------:|
|realType|获取数据真实类型||
|isObject|是否为对象||
|isRegexp|是否为正则表达式||
|isFunction|是否为函数||
|isImageUrl|判断 URL 是否为图片路径||
|isNumber|是否为纯数字||
|isEmpty|是否为空||
|isBoolean|是否为布尔值||
|isPromise|是否为 `Promise`||
|toBoolean|转换 `string` 布尔值||
|toLowerCamelCase|下划线转小驼峰||
|toUnderline|小驼峰转下划线分割||
|toPascalCase|中横线转大驼峰||
|formatThousandth|数字千分位||
|countDown|倒计时||
|debounce|防抖||
|debounceDecorator|防抖装饰器版||
|deepCopy|深拷贝||
|createRandomID|生成随机ID||
|objectKeyToCamelCase|Object key转换为小驼峰||
|ua|`navigator.userAgent` 进行解析||
|dCookie|`cookie` 操作||
|generateTree|一维数组转树形数据||
|throwError|统一报错信息处理||
|debugWarn|警告信息统一处理||
|deleteArrayItems|指定删除数组的某些元素||
|pickLastItem|选择数组的最后一项元素||
|treeToMap|树形数据转 map||
|firstLetterLowercase|首字母小写||
|firstLetterUppercase|首字母大写||

### ua 示例

Expand Down
12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@xuanmo/utils",
"version": "0.0.2",
"version": "0.0.3",
"author": {
"name": "xuanmo",
"email": "[email protected]"
Expand All @@ -15,7 +15,7 @@
"build": "npm run clear && rollup -c --bundleConfigAsCjs",
"clear": "rimraf dist",
"lint": "eslint src/**/*.ts --fix",
"test": "jest test/"
"test": "npm run build && jest test/"
},
"license": "MIT",
"repository": {
Expand All @@ -31,15 +31,17 @@
"@rollup/plugin-typescript": "^11.0.0",
"@typescript-eslint/eslint-plugin": "^5.54.0",
"@typescript-eslint/parser": "^5.54.0",
"@xuanmo/prettier-config": "^0.0.2",
"husky": "^7.0.4",
"jest": "^27.2.5",
"rimraf": "^3.0.2",
"rollup": "^3.18.0",
"rollup": "^4.24.0",
"rollup-plugin-uglify": "^6.0.4",
"tslib": "^2.3.0",
"typescript": "^4.3.4"
"typescript": "^5.6.3"
},
"hooks": {
"pre-commit": "npm test"
}
},
"prettier": "@xuanmo/prettier-config"
}
36 changes: 0 additions & 36 deletions src/URL.ts

This file was deleted.

3 changes: 1 addition & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ export * from './base'
export { default as deepCopy } from './deep-copy'
export * from './debounce'
export { default as countDown } from './count-down'
export * from './URL'
export { default as ua } from './ua'
export * from './ua'
export * from './cookie'
export * from './tree'
export * from './debug'
Expand Down
15 changes: 15 additions & 0 deletions src/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,18 @@ export function objectKeyToCamelCase(source: any, filterKey?: string, separator?
}
return result
}

/**
* 排除对象中的某些属性
* @param data 原始对象
* @param keys 要排除的属性
*/
export function exclude<T extends Record<string, any>, K extends keyof T>(data: T, keys: K[]) {
const result = {} as T
for (const [key, value] of Object.entries(data)) {
if (!keys.includes(key as K)) {
result[key as K] = value
}
}
return result as Exclude<T, K>
}
24 changes: 23 additions & 1 deletion src/string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,32 @@ export const toPascalCase = (str: string): string => {
*/
export const createRandomID = (length = 12): string => {
const result: string[] = []
const word = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')
const word = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
const wordLength = word.length
for (let i = 0; i < length; i++) {
result.push(word[Math.round(Math.random() * wordLength)])
}
return result.join('')
}

/**
* 首字母大写
* @param str
*/
export const firstLetterUppercase = <T extends string>(str: T) => {
const [first, ...rest] = str
return `${first.toUpperCase()}${rest.join('')}` as FirstLetterUppercase<T>
}

/**
* 首字母小写
* @param str
*/
export const firstLetterLowercase = <T extends string>(str: T) => {
const [first, ...rest] = str
return `${first.toLowerCase()}${rest.join('')}` as FirstLetterLowercase<T>
}

export type FirstLetterUppercase<T extends string> = T extends `${infer First}${infer Rest}` ? `${Uppercase<First>}${Rest}` : T

export type FirstLetterLowercase<T extends string> = T extends `${infer First}${infer Rest}` ? `${Lowercase<First>}${Rest}` : T
17 changes: 9 additions & 8 deletions src/ua.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class UA {
*/
constructor(userAgent: string) {
this.agent = userAgent
this.init()
this.format()
const { browser, browserVersion, osVersion } = this.info
this.info = {
...this.info,
Expand All @@ -125,7 +125,7 @@ class UA {
}
}

private init() {
private format() {
try {
this.getSystemName()
this.getBrowserName()
Expand Down Expand Up @@ -180,7 +180,7 @@ class UA {
}

if (/^Macintosh/i.test($1)) {
[, osVersion] = $1.match(/X\s((\d+(_|\.))+\d+)/) || []
[, osVersion] = $1.match(/X\s((\d+([_.]))+\d+)/) || []
this.info.os = 'Macintosh'
this.info.device = 'PC'
this.info.osVersion = osVersion?.replace(/_/g, '.') ?? 'Unknown'
Expand Down Expand Up @@ -237,11 +237,11 @@ class UA {

this.info = {
...this.info,
...this._formatBrowserVersion(browser[0])
...this.formatBrowserVersion(browser[0])
}
}

_formatBrowserVersion(str: string): Browser {
private formatBrowserVersion(str: string): Browser {
try {
// ie 浏览器版本对照
const ieVersionMap: any = {
Expand All @@ -250,12 +250,13 @@ class UA {
'6.0': 10,
'7.0': 11
}
const { name, version } = str.match(/(?<name>[a-z\d]+)(\/|\s)(?<version>(\d+\.)+\d+)/i)?.groups ?? {}

const [name, , version] = str.match(/([a-z\d]+)(\/|\s)((\d+\.)+\d+)/i) || []

// 遍历查出浏览器名称,名称支持正则所以需要遍历查找
let browserName: any = {}
for (const [key, value] of Object.entries(this.browserNameMap)) {
if (new RegExp(key).test(name)) {
if (new RegExp(key).test(name!)) {
browserName = value
break
}
Expand Down Expand Up @@ -283,7 +284,7 @@ class UA {
}
}

export default function(agent = navigator.userAgent) {
export const ua = (agent = navigator.userAgent) => {
const ua: UA = new UA(agent)
return ua.info
}
7 changes: 6 additions & 1 deletion test/object.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { objectKeyToCamelCase } = require('../dist/index.cjs')
const { objectKeyToCamelCase, exclude } = require('../dist/index.cjs')

const expected = {
name: 'xuanmo',
Expand Down Expand Up @@ -37,3 +37,8 @@ const received = {
test('objectKeyToCamelCase', () => {
expect(JSON.stringify(objectKeyToCamelCase(expected, '', ['\\.']))).toBe(JSON.stringify(received))
})

test('exclude', () => {
const obj = { a: 1, b: 2, c: 3 }
expect(exclude(obj, ['a'])).toEqual({ b: 2, c: 3 })
})
12 changes: 12 additions & 0 deletions test/string.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const {
firstLetterUppercase,
firstLetterLowercase
} = require('../dist/index.cjs')

test('firstLetterUppercase', () => {
expect(firstLetterUppercase('tom')).toBe('Tom')
})

test('firstLetterLowercase', () => {
expect(firstLetterLowercase('Tom')).toBe('tom')
})
13 changes: 13 additions & 0 deletions test/ua.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const { ua } = require('../dist/index.cjs')

test('ua', () => {
expect(ua('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36')).toEqual({
browser: 'Chrome',
browserZH: 'Chrome',
browserVersion: '/',
os: 'Macintosh',
osVersion: '10.15.7',
device: 'PC',
engine: 'WebKit'
})
})
6 changes: 5 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@
"allowJs": false,
"strict": true,
"noUnusedLocals": true,
"downlevelIteration": true,
"experimentalDecorators": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"removeComments": false,
"lib": ["esnext", "dom"],
"lib": [
"esnext",
"dom"
],
"emitDeclarationOnly": true,
"declaration": true,
"declarationMap": false,
Expand Down
Loading

0 comments on commit 51b42ba

Please sign in to comment.