update stringify.js

This commit is contained in:
wxzhang 2022-03-15 21:38:15 +08:00
parent a594b51cb6
commit 353234cd01
5 changed files with 100 additions and 26 deletions

22
packages/demo/data.js Normal file
View File

@ -0,0 +1,22 @@
module.exports = {
"name" : "张三丰",
"age" : 12,
"active" : true,
"address" : [
"北京市",
"福建省泉州市\n洛阳镇"
],
"posts" : {
"title" : "标题",
"content": "内容"
},
"产品清单\t{}": [
"手机",
"电脑"
],
"产品价格" : {
"手机": 1299,
"电脑": 3999
},
"产品\\清单" : 1
}

View File

@ -1,28 +1,42 @@
const { objectToString } = require("../tools/stringify") const objectToString = require("../tools/stringify")
const path = require("path"); const path = require("path");
const fs = require("fs"); const fs = require("fs");
const k1 = "产品清单\t{}"
const k2 = "产品\\清单"
const data = { const data = {
name:"张三丰", name:"张三丰",
age:12, age:12,
active:true, active:true,
address:[ address:[
"北京市", "北京市",
"福建省泉州市" "福建省泉州市\n洛阳镇"
], ],
posts:{ posts:{
title:"标题", title:"标题",
content:"内容", content:"内容",
//comments:[] //comments:[]
}, },
"产品清单":[ [k1]:[
"手机", "手机",
"电脑" "电脑"
] ],
"产品价格":{
"手机":1299,
"电脑":3999
},
[k2]:1
} }
const result = objectToString(data) const result = objectToString(data)
console.log(result) console.log(result)
fs.writeFileSync(path.join(__dirname,"./data.js"),`module.exports = ${result}`)
const loaded = require("./data.js")
console.log(loaded[k1])
console.log(loaded[k2])

View File

@ -13,14 +13,16 @@ const readJson = require("readjson")
const createLogger = require("logsets") const createLogger = require("logsets")
const { replaceInterpolateVars,getDataTypeName } = require("@voerkai18n/runtime") const { replaceInterpolateVars,getDataTypeName } = require("@voerkai18n/runtime")
const { findModuleType,createPackageJsonFile } = require("./utils") const { findModuleType,createPackageJsonFile } = require("./utils")
const stringify = require("./stringify")
const logger = createLogger() const logger = createLogger()
const { t } = require("./languages") const { t } = require("./languages")
// 捕获翻译文本正则表达式一:缺点:当t(xxx,...复杂的表达式时不能正确匹配....) // 捕获翻译文本正则表达式一: 能匹配完整的t(xx,...)函数调用如果t函数调用不完整则不能匹配到
// 但是当t(xxx,...复杂的表达式时....)则不能正确匹配到,因此放弃该正则表达式
// const DefaultTranslateExtractor = String.raw`\b{funcName}\(\s*("|'){1}(?:((?<namespace>\w+)::))?(?<text>.*?)(((\1\s*\)){1})|((\1){1}\s*(,(\w|\d|(?:\{.*\})|(?:\[.*\])|([\"\'\(].*[\"\'\)]))*)*\s*\)))` // const DefaultTranslateExtractor = String.raw`\b{funcName}\(\s*("|'){1}(?:((?<namespace>\w+)::))?(?<text>.*?)(((\1\s*\)){1})|((\1){1}\s*(,(\w|\d|(?:\{.*\})|(?:\[.*\])|([\"\'\(].*[\"\'\)]))*)*\s*\)))`
// 捕获翻译文本正则表达式二: 能够支持复杂的表达式但是当提供不完整的t函数定义时也会进行匹配提取 比如t // 捕获翻译文本正则表达式二: 能够支持复杂的表达式但是当提供不完整的t函数定义时也会进行匹配提取
const DefaultTranslateExtractor = String.raw`\bt\(\s*("|'){1}(?:((?<namespace>\w+)::))?(?<text>.*?)(?=(\1\s*\))|(\1\s*\,))` const DefaultTranslateExtractor = String.raw`\bt\(\s*("|'){1}(?:((?<namespace>\w+)::))?(?<text>.*?)(?=(\1\s*\))|(\1\s*\,))`
@ -314,7 +316,7 @@ function updateLanguageFile(fromTexts,toLangFile,options){
// 默认的overwrite // 默认的overwrite
if(!["merge","sync"].includes(updateMode)){ if(!["merge","sync"].includes(updateMode)){
fs.writeFileSync(toLangFile,JSON.stringify(targetTexts,null,4)) fs.writeFileSync(toLangFile,stringify(targetTexts))
return return
} }
let targetTexts = {} let targetTexts = {}
@ -349,7 +351,7 @@ function updateLanguageFile(fromTexts,toLangFile,options){
targetTexts[text] = sourceLangs targetTexts[text] = sourceLangs
} }
}) })
fs.writeFileSync(toLangFile,JSON.stringify(targetTexts,null,4)) fs.writeFileSync(toLangFile,stringify(targetTexts))
} }
@ -409,7 +411,7 @@ module.exports = function(options={}){
updateLanguageFile(texts,langFile,options) updateLanguageFile(texts,langFile,options)
logger.log(" √ 更新语言文件 : {}",path.relative(outputPath,langFile)) logger.log(" √ 更新语言文件 : {}",path.relative(outputPath,langFile))
}else{ }else{
fs.writeFileSync(langFile,JSON.stringify(texts,null,4)) fs.writeFileSync(langFile,stringify(texts))
logger.log(" √ 保存语言文件 : {}",path.relative(outputPath,langFile)) logger.log(" √ 保存语言文件 : {}",path.relative(outputPath,langFile))
} }
} }

View File

@ -1,15 +1,21 @@
{ {
"支持的语言\t: {}": { "工程项目所在目录" : {
"en": "Supported Languages\t: {}", "en" : "Project Directory",
"$file": [
"index.js"
]
},
"支持的语言\\t: {}": {
"en" : "支持的语言\\t: {}",
"$file": [ "$file": [
"compile.command.js", "compile.command.js",
"extract.plugin.js" "extract.plugin.js"
] ]
}, },
"工程项目所在目录": { "保存{}\\n" : {
"en": "Project Directory", "en" : "保存{}\\n",
"$file": [ "$file": [
"index.js" "stringify.js"
] ]
} }
} }

View File

@ -1,3 +1,33 @@
/**
* 实现将{}转化为字符串
*
* 为什么不使用JSON.stringify?
*
* 假设有这样的翻译内容
* {
* "保存{}\n": "Save{}\n",
* }
* 这个内容中包含了转义字符\nJSON.stringify会将\n转义为\\n
* 因此在保存后文件中就变成
* {
* "保存{}\\n": "Save{}\n",
* }
* 这个转义方式比较不符合我们的预期更关键的是在require("cn.js")
* 得到的是
* {
* "保存{}\\n": "Save{}\n",
* }
* 这样当我们调用t函数时就会找不到对应在的key
*
* 问题的关键就在于JSON.stringify对转义字符的处理不能符合我们的要求
*
* 因此不得不自己来处理转义字符.
*
* 使用objectToString方法后就可以确保在翻译文件中的转义字符能按预期的方式工作
*
*
*
*/
const { isPlainObject } = require("./utils") const { isPlainObject } = require("./utils")
/** /**
@ -10,15 +40,16 @@ const { isPlainObject } = require("./utils")
* @returns * @returns
*/ */
function escape(str){ function escape(str){
return str.replaceAll("\t","\\t") return str.replaceAll('\\','\\\\')
.replaceAll("\t","\\t")
.replaceAll("\n","\\n") .replaceAll("\n","\\n")
.replaceAll("\b","\\b") .replaceAll("\b","\\b")
.replaceAll("\r","\\r") .replaceAll("\r","\\r")
.replaceAll("\f","\\f") .replaceAll("\f","\\f")
.replaceAll("\\","\\\\")
.replaceAll("\'","\\'") .replaceAll("\'","\\'")
.replaceAll('\"','\\"') .replaceAll('\"','\\"')
.replaceAll('\v','\\v') .replaceAll('\v','\\v')
} }
/** /**
* 获取字符串的长度中文算两个字符 * 获取字符串的长度中文算两个字符
@ -62,7 +93,7 @@ function objectToString(obj,{indent=4,alignKey=true}={}){
} }
results.push(item) results.push(item)
}) })
endChar =" ".repeat((level-1) * indent) + ( last ? "]" : "]") endChar =" ".repeat((level-1) * indent) + "]"
return beginChar + results.map(item=>{ return beginChar + results.map(item=>{
return `${" ".repeat(level * indent)}${item}` return `${" ".repeat(level * indent)}${item}`
}).join("\n") + endChar }).join("\n") + endChar
@ -73,7 +104,7 @@ function objectToString(obj,{indent=4,alignKey=true}={}){
let alignIndent = 0 let alignIndent = 0
Object.entries(node).forEach(([key,value],index)=>{ Object.entries(node).forEach(([key,value],index)=>{
const isLastItem = index ===length-1 const isLastItem = index ===length-1
alignIndent = Math.max(getStringWidth(key),alignIndent) alignIndent = Math.max(getStringWidth(escape(key)),alignIndent)
let item = [`${indentSpace}"${escape(key)}"`,value] let item = [`${indentSpace}"${escape(key)}"`,value]
if(Array.isArray(value) || isPlainObject(value)){ if(Array.isArray(value) || isPlainObject(value)){
item[1] = nodeToString(value, level,isLastItem) item[1] = nodeToString(value, level,isLastItem)
@ -92,10 +123,10 @@ function objectToString(obj,{indent=4,alignKey=true}={}){
} }
results.push(item) results.push(item)
}) })
endChar =" ".repeat((level-1) * indent) + ( last ? "}" : "}") endChar =" ".repeat((level-1) * indent) + "}"
return beginChar + results.map(item=>{ return beginChar + results.map(item=>{
if(alignKey){ if(alignKey){
return `${item[0]}${ " ".repeat(alignIndent-getStringWidth(item[0].trim())+2)}: ${item[1]}` return `${item[0]}${" ".repeat(alignIndent-getStringWidth(item[0].trim())+2)}: ${item[1]}`
}else{ }else{
return `${item[0]}: ${item[1]}` return `${item[0]}: ${item[1]}`
} }
@ -104,8 +135,7 @@ function objectToString(obj,{indent=4,alignKey=true}={}){
} }
return nodeToString(obj,0,true) return nodeToString(obj,0,true)
} }
module.exports = { module.exports = objectToString
objectToString,
getStringWidth
}