Skip to content

Commit

Permalink
feat(utils): 新增 StringTemplate
Browse files Browse the repository at this point in the history
  • Loading branch information
fjc0k committed May 26, 2023
1 parent a354746 commit 7a62e93
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 12 deletions.
64 changes: 64 additions & 0 deletions src/utils/StringTemplate.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { StringTemplate } from './StringTemplate'

describe('StringTemplate', () => {
test('ok', () => {
expect(
StringTemplate.render('{用户}爱你', {
用户: 'hello',
}),
).toBe('hello爱你')
expect(
StringTemplate.render('{用户}爱你', {
用户: () => 'hello',
}),
).toBe('hello爱你')
expect(
StringTemplate.render('{用户:2}爱你', {
用户: (id: number) => `hello${id}`,
}),
).toBe('hello2爱你')
expect(
StringTemplate.render('{用户:2,xx}爱你', {
用户: (id: number, type: string) => `hello${id}${type}`,
}),
).toBe('hello2xx爱你')
expect(
StringTemplate.render(
`{用户性别}爱你{{用户性别==='男'?'啊':'哟' }}`,
{
用户性别: '男',
},
{
code: true,
},
),
).toBe('男爱你啊')
expect(
StringTemplate.render(
`{用户性别}爱你{{用户性别==='男'?'啊':'哟' }}`,
{
用户性别: '女',
},
{
code: true,
},
),
).toBe('女爱你哟')
expect(
StringTemplate.render('{用户}爱你,${用户}', {
用户: 'hello',
}),
).toBe('hello爱你,$hello')
expect(
StringTemplate.render(
'{用户}爱你,${用户}',
{
用户: 'hello',
},
{
code: true,
},
),
).toBe('hello爱你,${用户}')
})
})
57 changes: 57 additions & 0 deletions src/utils/StringTemplate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
export interface StringTemplateRenderOptions {
/** 是否启用代码渲染,需环境支持 eval */
code?: boolean
}

/**
* 字符串模板。
*/
export class StringTemplate {
/**
* 渲染字符串模板。语法:
*
* - 用 `{key}` 直接替换;
* - 用 `{key:param1,param2}` 执行函数替换;
* - 用 `{{key==='test'?'hi':'hello'}}` 执行代码替换(内部使用 eval 实现,需开启选项里的 `code` 参数)。
*
* @param template 要渲染的模板
* @param data 渲染数据
* @param options 渲染选项
* @returns 返回渲染后字符串
*/
static render(
template: string,
data: Record<string, any>,
options?: StringTemplateRenderOptions,
) {
const enableCode = !!options?.code
const keys = Object.keys(data)
for (const key of keys) {
template =
typeof data[key] === 'function'
? template.replace(
new RegExp(`\\{${key}(:.+?)?\\}`, 'g'),
(_, params: string) => {
return data[key].call(
null,
...(params ? params.substring(1) : '').split(','),
)
},
)
: enableCode
? template.replace(new RegExp(`(?<!\\$)\\{${key}\\}`, 'g'), data[key])
: template.replaceAll(`{${key}}`, data[key])
}
if (enableCode) {
template = template.replace(/\{\{(.+?)\}\}/g, (_, code) => {
return eval(`
(() => {
const {${keys.join(',')}} = arguments[1];
return ${code};
})()
`)
})
}
return template
}
}
25 changes: 13 additions & 12 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,20 @@
/* istanbul ignore file */

export * from 'lodash-uni'

export * from './Calculator'
export * from './DataPacker'
export * from './EventBus'
export * from './GeoCoord'
export * from './LocalStoragePlus'
export * from './MiniProgramUrl'
export * from './RichUrl'
export * from './StringTemplate'
export * from './TreeData'
export * from './Wechat'
// @index(['./**/*.ts', '!./**/*.{test,perf}.*'], f => `export * from '${f.path}'`)
export * from './asRequiredDeep'
export * from './base64'
export * from './bindEvent'
export * from './Calculator'
export * from './cartesianProduct'
export * from './chooseFile'
export * from './chunkEqual'
Expand All @@ -21,14 +29,11 @@ export * from './constantCase'
export * from './copyTextToClipboard'
export * from './createSubmit'
export * from './createUrlQueryString'
export * from './DataPacker'
export * from './dedent'
export * from './defaultIndexTo'
export * from './devOrProd'
export * from './EventBus'
export * from './formatBytes'
export * from './formatNumber'
export * from './GeoCoord'
export * from './getCurrentScript'
export * from './getEnvironment'
export * from './getWechatPublicAccountQrcodeUrl'
Expand All @@ -37,12 +42,12 @@ export * from './ii'
export * from './inAndroid'
export * from './inBrowser'
export * from './inDeno'
export * from './indent'
export * from './inIOS'
export * from './inMiniProgram'
export * from './inNodeJS'
export * from './inTaro'
export * from './inWechatWebView'
export * from './indent'
export * from './isBlobUrl'
export * from './isChineseIDCardNumber'
export * from './isDataUrl'
Expand All @@ -56,26 +61,23 @@ export * from './jsonp'
export * from './keysStrict'
export * from './loadCss'
export * from './loadResource'
export * from './LocalStoragePlus'
export * from './loopUntil'
export * from './makeEnum'
export * from './md5'
export * from './MiniProgramUrl'
export * from './move'
export * from './omitStrict'
export * from './onceMeanwhile'
export * from './pMap'
export * from './parseDataUrl'
export * from './parseUrlQueryString'
export * from './pascalCase'
export * from './pickStrict'
export * from './placeKitten'
export * from './pMap'
export * from './prepareData'
export * from './readFile'
export * from './removeBlankChars'
export * from './removeEmojiChars'
export * from './removeNonWordChars'
export * from './RichUrl'
export * from './rot13'
export * from './roundTo'
export * from './run'
Expand All @@ -88,7 +90,6 @@ export * from './toFullWidthString'
export * from './toHalfWidthString'
export * from './toSingleLineString'
export * from './traverse'
export * from './TreeData'
export * from './wait'
export * from './Wechat'

// @endindex

0 comments on commit 7a62e93

Please sign in to comment.