更新替换变量函数
This commit is contained in:
parent
25f548535b
commit
f5cac613bb
125
src/index.js
125
src/index.js
@ -107,9 +107,9 @@ function parseFormatters(formatters){
|
|||||||
* 提取字符串中的插值变量
|
* 提取字符串中的插值变量
|
||||||
* @param {*} str
|
* @param {*} str
|
||||||
* @param {*} isFull =true 保留所有插值变量 =false 进行去重
|
* @param {*} isFull =true 保留所有插值变量 =false 进行去重
|
||||||
* @returns {Array} [[变量名称,[]],[变量名称,[formatter,formatter,...]],...]
|
* @returns {Array} [[变量名称,[],match],[变量名称,[formatter,formatter,...],match],...]
|
||||||
*/
|
*/
|
||||||
function getInterpolatedVars(str,isFull=false){
|
function getInterpolatedVars(str){
|
||||||
let results = [], match
|
let results = [], match
|
||||||
while ((match = varWithPipeRegexp.exec(str)) !== null) {
|
while ((match = varWithPipeRegexp.exec(str)) !== null) {
|
||||||
if (match.index === varWithPipeRegexp.lastIndex) {
|
if (match.index === varWithPipeRegexp.lastIndex) {
|
||||||
@ -118,17 +118,31 @@ function getInterpolatedVars(str,isFull=false){
|
|||||||
const varname = match.groups.varname || ""
|
const varname = match.groups.varname || ""
|
||||||
// 解析格式化器和参数 = [<formatterName>,[<formatterName>,[<arg>,<arg>,...]]]
|
// 解析格式化器和参数 = [<formatterName>,[<formatterName>,[<arg>,<arg>,...]]]
|
||||||
const formatters = parseFormatters(match.groups.formatters)
|
const formatters = parseFormatters(match.groups.formatters)
|
||||||
const varInfo = [varname,formatters]
|
const varInfo = [varname,formatters,match]
|
||||||
if(isFull) {
|
results.push(varInfo)
|
||||||
results.push([varname,formatters] )
|
|
||||||
}else{
|
|
||||||
if(results.findIndex(item=>item[0]===varInfo[0] && item[1].join()===varInfo[1].join()) === -1) results.push(varInfo)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 遍历插值变量,并进行替换插值变量
|
||||||
|
* @param {*} str
|
||||||
|
* @param {*} callback
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function forEachInterpolatedVars(str,callback){
|
||||||
|
let result=str, match
|
||||||
|
varWithPipeRegexp.lastIndex=0
|
||||||
|
while ((match = varWithPipeRegexp.exec(result)) !== null) {
|
||||||
|
const varname = match.groups.varname || ""
|
||||||
|
// 解析格式化器和参数 = [<formatterName>,[<formatterName>,[<arg>,<arg>,...]]]
|
||||||
|
const formatters = parseFormatters(match.groups.formatters)
|
||||||
|
if(typeof(callback)==="function"){
|
||||||
|
result=result.replaceAll(match[0],callback(varname,formatters))
|
||||||
|
}
|
||||||
|
varWithPipeRegexp.lastIndex=0
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 将要翻译内容提供了一个非文本内容时进行默认的转换
|
* 将要翻译内容提供了一个非文本内容时进行默认的转换
|
||||||
* - 对函数则执行并取返回结果()
|
* - 对函数则执行并取返回结果()
|
||||||
@ -220,7 +234,7 @@ function getDataTypeDefaultFormatter(scope,activeLanguage,dataType){
|
|||||||
let formattersCache = { $activeLanguage:null}
|
let formattersCache = { $activeLanguage:null}
|
||||||
function getFormatter(scope,activeLanguage,name){
|
function getFormatter(scope,activeLanguage,name){
|
||||||
if(formattersCache.$activeLanguage === activeLanguage) {
|
if(formattersCache.$activeLanguage === activeLanguage) {
|
||||||
if(name in formattersCache) return formattersCache[dataType]
|
if(name in formattersCache) return formattersCache[name]
|
||||||
}else{ // 当切换语言时需要清空缓存
|
}else{ // 当切换语言时需要清空缓存
|
||||||
formattersCache = { $activeLanguage:activeLanguage }
|
formattersCache = { $activeLanguage:activeLanguage }
|
||||||
}
|
}
|
||||||
@ -250,7 +264,7 @@ function executeFormatter(value,formatters){
|
|||||||
for(let formatter of formatters){
|
for(let formatter of formatters){
|
||||||
if(typeof(formatter) === "function") {
|
if(typeof(formatter) === "function") {
|
||||||
result = formatter(result)
|
result = formatter(result)
|
||||||
}else{ // 碰到无效的格式化器时,直接返回
|
}else{
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -272,31 +286,41 @@ function buildFormatters(scope,activeLanguage,formatters){
|
|||||||
let results = []
|
let results = []
|
||||||
for(let formatter of formatters){
|
for(let formatter of formatters){
|
||||||
if(formatter[0]){
|
if(formatter[0]){
|
||||||
results.push((v)=>{
|
const func = getFormatter(scope,activeLanguage,formatter[0])
|
||||||
return getFormatter(scope,activeLanguage,formatter[0])(v,...formatter[1])
|
if(typeof(func)==="function"){
|
||||||
})
|
results.push((v)=>{
|
||||||
|
return func(v,...formatter[1])
|
||||||
|
})
|
||||||
|
}else{// 格式化器无效或者没有定义时,查看当前值是否具有同名的方法,如果有则执行调用
|
||||||
|
results.push((v)=>{
|
||||||
|
if(typeof(v[formatter[0]])==="function"){
|
||||||
|
return v[formatter[0]].call(v,...formatter[1])
|
||||||
|
}else{
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
/**
|
* 字符串可以进行变量插值替换,
|
||||||
* 字符串可以进行变量插值替换,
|
* replaceInterpolatedVars("<模板字符串>",{变量名称:变量值,变量名称:变量值,...})
|
||||||
* replaceInterpolatedVars("<模板字符串>",{变量名称:变量值,变量名称:变量值,...})
|
* replaceInterpolatedVars("<模板字符串>",[变量值,变量值,...])
|
||||||
* replaceInterpolatedVars("<模板字符串>",[变量值,变量值,...])
|
* replaceInterpolatedVars("<模板字符串>",变量值,变量值,...])
|
||||||
* replaceInterpolatedVars("<模板字符串>",变量值,变量值,...])
|
*
|
||||||
*
|
- 当只有两个参数并且第2个参数是{}时,将第2个参数视为命名变量的字典
|
||||||
- 当只有两个参数并且第2个参数是{}时,将第2个参数视为命名变量的字典
|
replaceInterpolatedVars("this is {a}+{b},{a:1,b:2}) --> this is 1+2
|
||||||
replaceInterpolatedVars("this is {a}+{b},{a:1,b:2}) --> this is 1+2
|
- 当只有两个参数并且第2个参数是[]时,将第2个参数视为位置参数
|
||||||
- 当只有两个参数并且第2个参数是[]时,将第2个参数视为位置参数
|
replaceInterpolatedVars"this is {}+{}",[1,2]) --> this is 1+2
|
||||||
replaceInterpolatedVars"this is {}+{}",[1,2]) --> this is 1+2
|
- 普通位置参数替换
|
||||||
- 普通位置参数替换
|
replaceInterpolatedVars("this is {a}+{b}",1,2) --> this is 1+2
|
||||||
replaceInterpolatedVars("this is {a}+{b}",1,2) --> this is 1+2
|
-
|
||||||
-
|
this == scope == { formatters: {}, ... }
|
||||||
this == scope == { formatters: {}, ... }
|
* @param {*} template
|
||||||
* @param {*} template
|
* @returns
|
||||||
* @returns
|
*/
|
||||||
*/
|
|
||||||
function replaceInterpolatedVars(template,...args) {
|
function replaceInterpolatedVars(template,...args) {
|
||||||
const scope = this
|
const scope = this
|
||||||
// 当前激活语言
|
// 当前激活语言
|
||||||
@ -306,37 +330,22 @@ function replaceInterpolatedVars(template,...args) {
|
|||||||
// ****************************变量插值****************************
|
// ****************************变量插值****************************
|
||||||
if(args.length===1 && typeof(args[0]) === "object" && !Array.isArray(args[0])){
|
if(args.length===1 && typeof(args[0]) === "object" && !Array.isArray(args[0])){
|
||||||
// 读取模板字符串中的插值变量列表
|
// 读取模板字符串中的插值变量列表
|
||||||
// [[var1:[formatter,formatter,...]],[var2:[formatter,formatter,...]],...}
|
// [[var1,[formatter,formatter,...],match],[var2,[formatter,formatter,...],match],...}
|
||||||
let interpVars = getInterpolatedVars(template)
|
|
||||||
let varValues = args[0]
|
let varValues = args[0]
|
||||||
if(interpVars.length===0) return template // 没有变量插值则的返回原字符串
|
return forEachInterpolatedVars(template,(varname,formatters)=>{
|
||||||
// 开始处理插值变量
|
// 1. 取得格式化器函数列表
|
||||||
for(let [name,formatters] of interpVars){
|
|
||||||
// 1. 取得格式化器函数列表 formatters=[[格式化器名称,[参数,参数,...]],[格式化器名称,[参数,参数,...]]]
|
|
||||||
const formatterFuncs = buildFormatters(scope,activeLanguage,formatters)
|
const formatterFuncs = buildFormatters(scope,activeLanguage,formatters)
|
||||||
// 2. 取变量值
|
// 2. 取变量值
|
||||||
let value = (name in varValues) ? varValues[name] : ''
|
let value = (varname in varValues) ? varValues[varname] : ''
|
||||||
// 3. 查找每种数据类型默认格式化器,并添加到formatters最前面,默认数据类型格式化器优先级最高
|
// 3. 查找每种数据类型默认格式化器,并添加到formatters最前面,默认数据类型格式化器优先级最高
|
||||||
const defaultFormatter = getDataTypeDefaultFormatter(scope,activeLanguage,getDataTypeName(value))
|
const defaultFormatter = getDataTypeDefaultFormatter(scope,activeLanguage,getDataTypeName(value))
|
||||||
if(defaultFormatter){
|
if(defaultFormatter){
|
||||||
formatterFuncs.splice(0,0,defaultFormatter)
|
formatterFuncs.splice(0,0,defaultFormatter)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 执行格式化器
|
// 4. 执行格式化器
|
||||||
value = executeFormatter(value,formatterFuncs)
|
value = executeFormatter(value,formatterFuncs)
|
||||||
|
return value
|
||||||
// 5. 进行值替换
|
})
|
||||||
// 如果变量中包括|管道符,则需要进行转换以适配更宽松的写法,比如data|time能匹配"data |time","data | time"等
|
|
||||||
let nameRegexp =
|
|
||||||
if(formatters.length===0){
|
|
||||||
nameRegexp = new RegExp(String.raw`\{\s*${name}\s*\}`,"gm")
|
|
||||||
}else{
|
|
||||||
nameRegexp = new RegExp(`${name}\\s*\\|\\s*${formatters.join("\\s*\\|\\s*")}`,"gm")
|
|
||||||
}
|
|
||||||
|
|
||||||
result= result.replaceAll(nameRegexp,transformToString(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
// ****************************位置插值****************************
|
// ****************************位置插值****************************
|
||||||
// 如果只有一个Array参数,则认为是位置变量列表,进行展开
|
// 如果只有一个Array参数,则认为是位置变量列表,进行展开
|
||||||
@ -357,7 +366,7 @@ function replaceInterpolatedVars(template,...args) {
|
|||||||
formatterFuncs.splice(0,0,defaultFormatter)
|
formatterFuncs.splice(0,0,defaultFormatter)
|
||||||
}
|
}
|
||||||
value = executeFormatter(value,formatterFuncs)
|
value = executeFormatter(value,formatterFuncs)
|
||||||
result=result.replace(match,transformToString(value))
|
result = result.replace(match,transformToString(value))
|
||||||
i+=1
|
i+=1
|
||||||
}else{
|
}else{
|
||||||
break
|
break
|
||||||
|
@ -16,12 +16,12 @@ const scope1 ={
|
|||||||
"*":{
|
"*":{
|
||||||
$types:{
|
$types:{
|
||||||
Date:(v)=>dayjs(v).format('YYYY/MM/DD'),
|
Date:(v)=>dayjs(v).format('YYYY/MM/DD'),
|
||||||
Boolean:(v)=>v?"True":"False",
|
Boolean:(v)=>v?"True":"False",
|
||||||
},
|
},
|
||||||
|
sum:(v,n=1)=>v+n,
|
||||||
|
double:(v)=>v*2,
|
||||||
upper:(v)=>v.toUpperCase(),
|
upper:(v)=>v.toUpperCase(),
|
||||||
lower:(v)=>v.toLowerCase(),
|
lower:(v)=>v.toLowerCase()
|
||||||
padStart:(v,len,pad)=>v.padStart(len,pad),
|
|
||||||
padStart:(v,len,pad)=>v.padStart(len,pad),
|
|
||||||
},
|
},
|
||||||
cn:{
|
cn:{
|
||||||
$types:{
|
$types:{
|
||||||
@ -105,7 +105,18 @@ test("替换翻译内容的位置插值变量",done=>{
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("替换翻译内容的命名插值变量",done=>{
|
test("替换翻译内容的命名插值变量",done=>{
|
||||||
expect(replaceVars("{a}{b}{c}",{a:1,b:2,c:3})).toBe("123");
|
expect(replaceVars("{a}{b}{c}",{a:11,b:22,c:33})).toBe("112233");
|
||||||
expect(replaceVars("{a}{b}{c}{a}{b}{c}",{a:1,b:"2",c:3})).toBe("123123");
|
expect(replaceVars("{a}{b}{c}{a}{b}{c}",{a:1,b:"2",c:3})).toBe("123123");
|
||||||
done()
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("命名插值变量使用格式化器",done=>{
|
||||||
|
// 提供无效的格式化器,直接忽略
|
||||||
|
expect(replaceVars("{a|x}{b|x|y}{c|}",{a:1,b:2,c:3})).toBe("123");
|
||||||
|
expect(replaceVars("{a|x}{b|x|y}{c|double}",{a:1,b:2,c:3})).toBe("126");
|
||||||
|
// 默认的字符串格式化器,不需要定义使用字符串方法
|
||||||
|
expect(replaceVars("{a|x}{b|x|y}{c|double}",{a:1,b:2,c:3})).toBe("126");
|
||||||
|
expect(replaceVars("{a|padStart(10)}",{a:"123"})).toBe(" 123");
|
||||||
|
expect(replaceVars("{a|padStart(10)|trim}",{a:"123"})).toBe("123");
|
||||||
|
done()
|
||||||
})
|
})
|
Loading…
x
Reference in New Issue
Block a user