Skip to content

Commit

Permalink
feat: 增加@xpart-utils/string的template方法,以支撑log函数实现
Browse files Browse the repository at this point in the history
  • Loading branch information
vtrbo committed Jul 4, 2024
1 parent e9f566b commit 6f9f5b6
Show file tree
Hide file tree
Showing 13 changed files with 172 additions and 84 deletions.
3 changes: 3 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
strict-peer-dependencies=false
auto-install-peers=true
shamefully-hoist=true
7 changes: 7 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,11 @@ export default defineConfig(
'unicorn/error-message': 'off',
},
},
// @xparcai-utils/log 包取消禁用console
{
files: ['packages/log/**/*.*'],
rules: {
'no-console': 'off',
},
},
)
4 changes: 0 additions & 4 deletions packages/is/__test__/isHttp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,5 @@ describe('@xparcai-utils/is', () => {
isHttp.setCondition('s')
expect(isHttp('http://xparcai.com')).toBe(false)
expect(isHttp('https://xparcai.com')).toBe(true)

// 设置默认值调用
expect(isHttp.setCondition('s')('http://xparcai.com')).toBe(false)
expect(isHttp.setCondition('s')('https://xparcai.com')).toBe(true)
})
})
2 changes: 1 addition & 1 deletion packages/is/src/isEmptyString.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ import { isString } from './isString'
* @param str 某个字符串
* @returns 是否为空字符串
*/
export function isEmptyString(str: unknown):boolean {
export function isEmptyString(str: unknown): boolean {
return isString(str) && str !== ''
}
1 change: 0 additions & 1 deletion packages/is/src/isHttp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,4 @@ export function isHttp(url: string, condition: Condition = _condition): boolean
*/
isHttp.setCondition = function (condition: Condition = _condition) {
_condition = condition
return isHttp
}
14 changes: 7 additions & 7 deletions packages/log/__test__/log.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,20 @@ describe('@xparcai-utils/log', () => {
const data = [
{ id: 1, name: 'Alice', age: 25 },
{ id: 2, name: 'Bob', age: 30 },
{ id: 3, name: 'Charlie', age: 35 }
{ id: 3, name: 'Charlie', age: 35 },
]
const columns = [
{
title: 'ID',
key: 'id'
title: 'ID',
key: 'id',
},
{
title: '名字',
key: 'name'
title: '名字',
key: 'name',
},
{
title: '年龄',
key: 'age'
title: '年龄',
key: 'age',
},
]
expect(log.table(data, columns))
Expand Down
3 changes: 3 additions & 0 deletions packages/log/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,8 @@
"clean": "run-s clean:*",
"clean:dist": "rimraf dist",
"clean:deps": "rimraf node_modules"
},
"devDependencies": {
"@xparcai-utils/is": "workspace:*"
}
}
138 changes: 70 additions & 68 deletions packages/log/src/log.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { isEmptyArray, isEmptyString } from '@xparcai-utils/is'
type textOption = {
color?: string,
borderColor?: string,
borderStyle?: string,
borderWidth?: string,
fontSize?: string,
padding?: string,
borderRadius?: string,

interface textOption {
color?: string
borderColor?: string
borderStyle?: string
borderWidth?: string
fontSize?: string
padding?: string
borderRadius?: string
backgroundColor?: string
}
type tableColum = {
interface tableColum {
title: string
key: string
}
type tableOption = {
interface tableOption {
color?: string
backgroundColor?: string
padding?: string
Expand All @@ -24,12 +25,12 @@ function prettyLog() {
`%c ${title} %c ${text} %c`,
`background:${option.backgroundColor};border:${option.borderWidth} ${option.borderStyle} ${option.borderColor}; padding: ${option.padding}; border-radius: ${option.borderRadius}; color: #fff;`,
`border:${option.borderWidth} ${option.borderStyle} ${option.borderColor}; padding: ${option.padding}; border-radius: ${option.borderRadius}; color: ${option.color};`,
'background:transparent'
);
};
'background:transparent',
)
}
const info = (textOrTitle: string, content: string = '', option: textOption = {}) => {
const title = isEmptyString(content) ? 'Info' : textOrTitle;
const text = isEmptyString(content) ? textOrTitle : content;
const title = isEmptyString(content) ? 'Info' : textOrTitle
const text = isEmptyString(content) ? textOrTitle : content
const defaultOption = {
color: '#909399',
borderColor: '#909399',
Expand All @@ -38,14 +39,14 @@ function prettyLog() {
fontSize: '12px',
padding: '1px',
borderRadius: '2px 0 0 2px',
backgroundColor: '#909399'
backgroundColor: '#909399',
}
const textOption = Object.assign(defaultOption, option)
prettyPrint(title, text, textOption);
};
prettyPrint(title, text, textOption)
}
const error = (textOrTitle: string, content: string = '', option: textOption = {}) => {
const title = isEmptyString(content) ? 'Error' : textOrTitle;
const text = isEmptyString(content) ? textOrTitle : content;
const title = isEmptyString(content) ? 'Error' : textOrTitle
const text = isEmptyString(content) ? textOrTitle : content
const defaultOption = {
color: '#F56C6C',
borderColor: '#F56C6C',
Expand All @@ -54,14 +55,14 @@ function prettyLog() {
fontSize: '12px',
padding: '1px',
borderRadius: '2px 0 0 2px',
backgroundColor: '#F56C6C'
backgroundColor: '#F56C6C',
}
const textOption = Object.assign(defaultOption, option)
prettyPrint(title, text, textOption);
};
const warning = (textOrTitle: string, content:string = '', option: textOption = {}) => {
const title = isEmptyString(content) ? 'Warning' : textOrTitle;
const text = isEmptyString(content) ? textOrTitle : content;
prettyPrint(title, text, textOption)
}
const warning = (textOrTitle: string, content: string = '', option: textOption = {}) => {
const title = isEmptyString(content) ? 'Warning' : textOrTitle
const text = isEmptyString(content) ? textOrTitle : content
const defaultOption = {
color: '#E6A23C',
borderColor: '#E6A23C',
Expand All @@ -70,14 +71,14 @@ function prettyLog() {
fontSize: '12px',
padding: '1px',
borderRadius: '2px 0 0 2px',
backgroundColor: '#E6A23C'
backgroundColor: '#E6A23C',
}
const textOption = Object.assign(defaultOption, option)
prettyPrint(title, text, textOption);
};
const success = (textOrTitle: string, content:string = '', option: textOption = {}) => {
const title = isEmptyString(content) ? 'Success ' : textOrTitle;
const text = isEmptyString(content) ? textOrTitle : content;
prettyPrint(title, text, textOption)
}
const success = (textOrTitle: string, content: string = '', option: textOption = {}) => {
const title = isEmptyString(content) ? 'Success ' : textOrTitle
const text = isEmptyString(content) ? textOrTitle : content
const defaultOption = {
color: '#67C23A',
borderColor: '#67C23A',
Expand All @@ -86,11 +87,11 @@ function prettyLog() {
fontSize: '12px',
padding: '1px',
borderRadius: '2px 0 0 2px',
backgroundColor: '#67C23A'
backgroundColor: '#67C23A',
}
const textOption = Object.assign(defaultOption, option)
prettyPrint(title, text, textOption);
};
prettyPrint(title, text, textOption)
}
const table = (tableData: any[], tableColumns: tableColum[], headerOption: tableOption = {}, bodyOption: tableOption = {}) => {
let canUse = true
let cantUseMsg = ''
Expand All @@ -103,29 +104,30 @@ function prettyLog() {
return
}
let theaderStr: string = ''
let tHeaderArr: string[] = []
let tBodyArr: string[] = []
const tHeaderArr: string[] = []
const tBodyArr: string[] = []
const defaultHeaderOption: tableOption = {
color: 'white',
backgroundColor: 'black',
padding: '2px 10px'
padding: '2px 10px',
}
const optionHeader : tableOption = Object.assign(defaultHeaderOption, headerOption)
const optionHeader: tableOption = Object.assign(defaultHeaderOption, headerOption)
const defaultBodyOption: tableOption = {
color: 'black',
backgroundColor: 'lightgray',
padding: '2px 10px'
padding: '2px 10px',
}
const optionBody: tableOption = Object.assign(defaultBodyOption, bodyOption)

for (let index = 0; index < tableColumns.length; index++) {
const item = tableColumns[index];
const item = tableColumns[index]
if (isEmptyString(item.title) || isEmptyString(item.key)) {
cantUseMsg = '请传入正确的tableColumns数据'
canUse = false
break
} else {
theaderStr = theaderStr + `%c ${item.title}`
}
else {
theaderStr = `${theaderStr}%c ${item.title}`
tHeaderArr.push(`color: ${optionHeader.color}; background-color: ${optionHeader.backgroundColor}; padding: ${optionHeader.padding};`)
tBodyArr.push(`color: ${optionBody.color}; background-color: ${optionBody.backgroundColor}; padding: ${optionBody.padding};`)
}
Expand All @@ -135,29 +137,29 @@ function prettyLog() {
return
}
// 输出头部
console.log(theaderStr,...tHeaderArr);
console.log(theaderStr, ...tHeaderArr)
// 循环输出body内容
tableData.forEach((row: any) => {
let tBodyStr = ''
tableColumns.forEach(item => {
tBodyStr = tBodyStr + `%c ${row[item.key]}`
tableColumns.forEach((item) => {
tBodyStr = `${tBodyStr}%c ${row[item.key]}`
})
console.log(tBodyStr, ...tBodyArr);
});
};
console.log(tBodyStr, ...tBodyArr)
})
}
const picture = (url: string, scale = 1) => {
const img = new Image();
img.crossOrigin = 'anonymous';
const img = new Image()
img.crossOrigin = 'anonymous'
img.onload = () => {
const c = document.createElement('canvas');
const ctx = c.getContext('2d');
const c = document.createElement('canvas')
const ctx = c.getContext('2d')
if (ctx) {
c.width = img.width;
c.height = img.height;
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, c.width, c.height);
ctx.drawImage(img, 0, 0);
const dataUri = c.toDataURL('image/png');
c.width = img.width
c.height = img.height
ctx.fillStyle = 'red'
ctx.fillRect(0, 0, c.width, c.height)
ctx.drawImage(img, 0, 0)
const dataUri = c.toDataURL('image/png')

console.log(
`%c sup?`,
Expand All @@ -167,21 +169,21 @@ function prettyLog() {
background-repeat: no-repeat;
background-size: ${img.width * scale}px ${img.height * scale}px;
color: transparent;
`
);
`,
)
}
};
img.src = url;
};
}
img.src = url
}

return {
info,
error,
warning,
success,
picture,
table
};
table,
}
}

export const log = prettyLog();
export const log = prettyLog()
2 changes: 1 addition & 1 deletion packages/object/src/deepCopy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export function deepCopy<T>(data: T): T
export function deepCopy<T, H extends object>(data: T, hash?: H): T

/**
* 深拷贝实现
* 实现函数
*/
export function deepCopy<T>(data: T, hash: any = new WeakMap()): T {
// 日期对象直接返回一个新的日期对象
Expand Down
16 changes: 16 additions & 0 deletions packages/string/__test__/template.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { describe, expect, it } from 'vitest'
import { template } from '../src/template'

describe('@xparcai-utils/string', () => {
const nmtp = 'hello {0}, {1}好!'
const jmtp = 'hello {name}, {time}好!'

it('template', () => {
expect(template(nmtp, 'xparcai', '早上')).toBe('hello xparcai, 早上好!')
expect(template(jmtp, { name: 'xparcai', time: '早上' })).toBe('hello xparcai, 早上好!')
expect(template(jmtp, { name: 'xparcai' }, '晚上')).toBe('hello xparcai, 晚上好!')
expect(template(jmtp, key => (key !== 'time' ? { time: '中午' } : { name: 'xparcai' }))).toBe('hello name, time好!')
expect(template(jmtp, key => (key === 'time' ? { time: '中午' } : {}), '[xparcai]')).toBe('hello [xparcai], 中午好!')
expect(template(jmtp, () => ({}), 'xparcai')).toBe('hello xparcai, xparcai好!')
})
})
3 changes: 3 additions & 0 deletions packages/string/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,8 @@
"clean": "run-s clean:*",
"clean:dist": "rimraf dist",
"clean:deps": "rimraf node_modules"
},
"devDependencies": {
"@xparcai-utils/is": "workspace:*"
}
}
42 changes: 42 additions & 0 deletions packages/string/src/template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { isFunction, isObject } from '@xparcai-utils/is'

type Value = string | number | bigint | undefined | null
type ValueObject = Record<string | number, Value>

/**
* 匿名字符串模板替换
* @param tp 字符串模板
* @param args 占位值
* @returns 替换后的字符串
*/
export function template(tp: string, ...args: Value[]): string

/**
* 混合字符串模板替换
* @param tp 字符串模板
* @param values 具名占位值集合,未提供值的统一使用 other 值填充
* @param other 匿名占位值,支持字符串和函数
* @returns 替换后的字符串
*/
export function template(tp: string, values: ValueObject | ((key: string) => ValueObject), other?: string | ((key: string) => string)): string

/**
* 实现函数
*/
export function template(tp: string, ...args: any[]): string {
const [values, other] = args
if (isFunction(values) || isObject(values)) {
return tp.replace(/\{(\w+)\}/g, (_, key) => {
const _values = isFunction(values) ? values(key) : values
return _values[key] || ((isFunction(other) ? other(key) : other) ?? key)
})
}
else {
return tp.replace(/\{(\d+)\}/g, (_, key) => {
const index = Number(key)
if (Number.isNaN(index))
return key
return args[index]
})
}
}
Loading

0 comments on commit 6f9f5b6

Please sign in to comment.