fis3-parser-react-i18n
Advanced tools
Comparing version 0.0.23-beta.11 to 0.0.23-beta.12
502
index.js
@@ -1,295 +0,247 @@ | ||
const {parse} = require('@babel/parser'); | ||
const {default: traverse} = require('@babel/traverse'); | ||
const {default: generate} = require('@babel/generator'); | ||
const t = require('@babel/types'); | ||
const {addNamed} = require('@babel/helper-module-imports'); | ||
const crypto = require('crypto'); | ||
const fs = require('fs'); | ||
const p = require('path'); | ||
const ignore = require('ignore'); | ||
var parse = require('@babel/parser').parse; | ||
var traverse = require('@babel/traverse').default; | ||
var generate = require('@babel/generator').default; | ||
var t = require('@babel/types'); | ||
var addNamed = require('@babel/helper-module-imports').addNamed; | ||
var crypto = require('crypto'); | ||
var fs = require('fs'); | ||
var p = require('path'); | ||
var ignore = require('ignore'); | ||
function hash(str) { | ||
const md5 = crypto.createHash('md5'); | ||
return md5.update(str).digest('hex'); | ||
var md5 = crypto.createHash('md5'); | ||
return md5.update(str).digest('hex'); | ||
} | ||
// Hmac算法: 需要配置一个密钥(俗称加盐) | ||
function hmacHash(str, secretKey) { | ||
const curSecretKey = secretKey || 'suda-i18n'; | ||
const md5 = crypto.createHmac('md5', curSecretKey); | ||
return md5.update(str).digest('hex'); | ||
var curSecretKey = secretKey || 'suda-i18n'; | ||
var md5 = crypto.createHmac('md5', curSecretKey); | ||
return md5.update(str).digest('hex'); | ||
} | ||
const zhExt = /[\u4e00-\u9fa5]+/; | ||
let baseLocale = null; | ||
var zhExt = /[\u4e00-\u9fa5]+/; | ||
var baseLocale = null; | ||
function noLocale(value, id, relativePath) { | ||
if (!baseLocale) { | ||
if (!baseLocale) { | ||
return false; | ||
} | ||
if (!baseLocale[id]) { | ||
console.log('\x1B[31m%s\x1B[0m', "\n\u3010i18n\u3011\u5728\u8BED\u6599\u5305\u4E2D\u672A\u53D1\u73B0\u4EE5\u4E0B\u5B57\u6BB5 ".concat(relativePath, "\uFF1A").concat(value, " \u8BF7\u6267\u884Ci18n update\n")); | ||
return true; | ||
} | ||
return false; | ||
} | ||
if (!baseLocale[id]) { | ||
console.log( | ||
'\x1B[31m%s\x1B[0m', | ||
`\n【i18n】在语料包中未发现以下字段 ${relativePath}:${value} 请执行i18n update\n` | ||
); | ||
return true; | ||
} | ||
return false; | ||
} | ||
function readChinese(languages) { | ||
const chinesePath = languages.find( | ||
language => language.name === 'zh-CN' | ||
).path; | ||
const chineseFunc = chinesePath => { | ||
let filePath = p.resolve(process.cwd(), chinesePath, 'zh-CN.ts'); | ||
if (!fs.existsSync(filePath)) { | ||
filePath = p.resolve(process.cwd(), chinesePath, 'zh-CN.js'); | ||
var chinesePath = languages.find(function (language) { return language.name === 'zh-CN'; }).path; | ||
var chineseFunc = function (chinesePath) { | ||
var filePath = p.resolve(process.cwd(), chinesePath, 'zh-CN.ts'); | ||
if (!fs.existsSync(filePath)) { | ||
filePath = p.resolve(process.cwd(), chinesePath, 'zh-CN.js'); | ||
} | ||
var code = fs.readFileSync(filePath, 'utf8'); | ||
var ast = parse(code, { | ||
sourceType: 'module', | ||
plugins: ['typescript'] | ||
}); | ||
traverse(ast, { | ||
ObjectProperty: function (path) { | ||
var key = path.node.key.value || path.node.key.name; | ||
var value = path.node.value.value || path.node.value.name; | ||
baseLocale[key] = value; | ||
} | ||
}); | ||
}; | ||
if (typeof chinesePath === 'string') { | ||
chineseFunc(chinesePath); | ||
} | ||
const code = fs.readFileSync(filePath, 'utf8'); | ||
const ast = parse(code, { | ||
sourceType: 'module', | ||
plugins: ['typescript'] | ||
}); | ||
traverse(ast, { | ||
ObjectProperty(path) { | ||
const key = path.node.key.value || path.node.key.name; | ||
const value = path.node.value.value || path.node.value.name; | ||
baseLocale[key] = value; | ||
} | ||
}); | ||
}; | ||
if (typeof chinesePath === 'string') { | ||
chineseFunc(chinesePath); | ||
} else if (Array.isArray(chinesePath)) { | ||
chinesePath.forEach(p => { | ||
chineseFunc(p); | ||
}); | ||
} | ||
else if (Array.isArray(chinesePath)) { | ||
chinesePath.forEach(function (p) { | ||
chineseFunc(p); | ||
}); | ||
} | ||
} | ||
module.exports = function (content, file, options) { | ||
const filePath = file.realpath; | ||
const {sameGit, list} = options.ignore || {}; | ||
const languages = options.languages; | ||
const ignoreList = list || []; | ||
if (sameGit) { | ||
const gitIgnore = fs | ||
.readFileSync(p.resolve(process.cwd(), '.gitignore')) | ||
.toString(); | ||
ignoreList.push(...gitIgnore.split('\n')); | ||
} | ||
const md5Hash = (str) => { | ||
if (options && options.md5secretKey) { | ||
return hmacHash(str, options.md5secretKey); | ||
var filePath = file.realpath; | ||
var _a = options.ignore || {}, sameGit = _a.sameGit, list = _a.list; | ||
var languages = options.languages; | ||
var ignoreList = list || []; | ||
if (sameGit) { | ||
var gitIgnore = fs | ||
.readFileSync(p.resolve(process.cwd(), '.gitignore')) | ||
.toString(); | ||
ignoreList.push.apply(ignoreList, gitIgnore.split('\n')); | ||
} | ||
return hash(str); | ||
}; | ||
try { | ||
const relativePath = p.relative(process.cwd(), filePath); | ||
const includes = ignore().add(options.includes); | ||
const included = includes.ignores(relativePath); | ||
const ig = ignore().add(ignoreList); | ||
if (ig.ignores(relativePath) && !included) { | ||
return content; | ||
var md5Hash = function (str) { | ||
if (options && options.md5secretKey) { | ||
return hmacHash(str, options.md5secretKey); | ||
} | ||
return hash(str); | ||
}; | ||
try { | ||
var relativePath = p.relative(process.cwd(), filePath); | ||
var includes = ignore().add(options.includes); | ||
var included = includes.ignores(relativePath); | ||
var ig = ignore().add(ignoreList); | ||
if (ig.ignores(relativePath) && !included) { | ||
return content; | ||
} | ||
} | ||
} catch (error) { | ||
return content; | ||
} | ||
const { | ||
source: importSource, | ||
imported: importImported, | ||
local: importLocal | ||
} = options.importInfo; | ||
const plugins = ['typescript', 'decorators-legacy']; | ||
if (/.*(tsx|jsx)$/.test(filePath)) { | ||
plugins.push('jsx'); | ||
} | ||
const ast = parse(content, { | ||
sourceType: 'module', | ||
errorRecovery: true, | ||
plugins | ||
}); | ||
if (ast.errors.length > 0) { | ||
console.warn(ast.errors); | ||
return content; | ||
} | ||
let needI18n = false; | ||
let i18nFnName = importLocal; | ||
if (!baseLocale) { | ||
baseLocale = {}; | ||
readChinese(languages); | ||
} | ||
const visitor = { | ||
Program: { | ||
exit(path) { | ||
if (needI18n) { | ||
let addI18n = true; | ||
path.traverse({ | ||
ImportDeclaration(importPath) { | ||
if (importPath.node.source.value.includes(importSource)) { | ||
const specifiers = importPath.node.specifiers; | ||
if (specifiers.length > 0) { | ||
const registerLocaleIndex = specifiers.findIndex( | ||
n => n.imported.name === importImported | ||
); | ||
addI18n = registerLocaleIndex === -1; | ||
catch (error) { | ||
return content; | ||
} | ||
var _b = options.importInfo, importSource = _b.source, importImported = _b.imported, importLocal = _b.local; | ||
var plugins = ['typescript', 'decorators-legacy']; | ||
if (/.*(tsx|jsx)$/.test(filePath)) { | ||
plugins.push('jsx'); | ||
} | ||
var ast = parse(content, { | ||
sourceType: 'module', | ||
errorRecovery: true, | ||
plugins: plugins | ||
}); | ||
if (ast.errors.length > 0) { | ||
console.warn(ast.errors); | ||
return content; | ||
} | ||
var needI18n = false; | ||
var i18nFnName = importLocal; | ||
if (!baseLocale) { | ||
baseLocale = {}; | ||
readChinese(languages); | ||
} | ||
var visitor = { | ||
Program: { | ||
exit: function (path) { | ||
if (needI18n) { | ||
var addI18n_1 = true; | ||
path.traverse({ | ||
ImportDeclaration: function (importPath) { | ||
if (importPath.node.source.value.includes(importSource)) { | ||
var specifiers = importPath.node.specifiers; | ||
if (specifiers.length > 0) { | ||
var registerLocaleIndex = specifiers.findIndex(function (n) { return n.imported.name === importImported; }); | ||
addI18n_1 = registerLocaleIndex === -1; | ||
} | ||
} | ||
} | ||
}); | ||
if (addI18n_1) { | ||
addNamed(path, importImported, importSource, { | ||
nameHint: importLocal, | ||
importPosition: 'after' | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
if (addI18n) { | ||
addNamed(path, importImported, importSource, { | ||
nameHint: importLocal, | ||
importPosition: 'after' | ||
}); | ||
} | ||
} | ||
} | ||
}, | ||
JSXText(path) { | ||
if ( | ||
t.isCallExpression(path.parent) && | ||
path.parent.callee.name === i18nFnName | ||
) { | ||
return; | ||
} | ||
if (zhExt.test(path.toString())) { | ||
const value = path.toString().trim(); | ||
const id = md5Hash(value); | ||
if (noLocale(value, id, relativePath)) { | ||
return; | ||
} | ||
const origininalValue = path.node.value; | ||
const trimmedValue = origininalValue.trim(); | ||
const valueIndex = origininalValue.indexOf(trimmedValue); | ||
const spacesLeft = origininalValue.substring(0, valueIndex); | ||
const spacesRight = origininalValue.substring( | ||
valueIndex + trimmedValue.length | ||
); | ||
path.replaceWithMultiple([ | ||
t.jsxText(spacesLeft), | ||
t.jsxExpressionContainer( | ||
t.callExpression(t.identifier(importLocal), [t.stringLiteral(id)]) | ||
), | ||
t.jsxText(spacesRight) | ||
]); | ||
needI18n = true; | ||
} | ||
}, | ||
TemplateLiteral(path) { | ||
if ( | ||
t.isCallExpression(path.parent) && | ||
path.parent.callee?.name === i18nFnName | ||
) { | ||
return; | ||
} | ||
if (zhExt.test(path.toString())) { | ||
// 处理这种情况 | ||
// <% if (data.usage === 0) { %> | ||
// ${'主要用于展示'} | ||
// <% } else if(data.usage === 1) { %> | ||
const node = path.node; | ||
let isCh = false; | ||
node.quasis && | ||
node.quasis.forEach(item => { | ||
if (zhExt.test(item.value.raw)) { | ||
isCh = true; | ||
}, | ||
JSXText: function (path) { | ||
if (t.isCallExpression(path.parent) && | ||
path.parent.callee.name === i18nFnName) { | ||
return; | ||
} | ||
}); | ||
if (isCh) { | ||
const variables = []; | ||
let i = 0; | ||
const value = path | ||
.toString() | ||
.replace(/^`|`$/g, '') | ||
.replace(/\$\{([\s\S]+?)\}/g, (...agr) => { | ||
i++; | ||
variables.push({ | ||
id: i, | ||
name: agr[1] | ||
}); | ||
return `{{@${i}}}`; | ||
}); | ||
const id = md5Hash(value); | ||
if (noLocale(value, id, relativePath)) { | ||
return; | ||
} | ||
path.replaceWith( | ||
t.callExpression(t.identifier(importLocal), [ | ||
t.stringLiteral(id), | ||
t.objectExpression( | ||
node.expressions.map((item, index) => { | ||
return t.objectProperty( | ||
t.stringLiteral(`@${index + 1}`), | ||
item | ||
); | ||
}) | ||
) | ||
]) | ||
); | ||
needI18n = true; | ||
if (zhExt.test(path.toString())) { | ||
var value = path.toString().trim(); | ||
var id = md5Hash(value); | ||
if (noLocale(value, id, relativePath)) { | ||
return; | ||
} | ||
var origininalValue = path.node.value; | ||
var trimmedValue = origininalValue.trim(); | ||
var valueIndex = origininalValue.indexOf(trimmedValue); | ||
var spacesLeft = origininalValue.substring(0, valueIndex); | ||
var spacesRight = origininalValue.substring(valueIndex + trimmedValue.length); | ||
path.replaceWithMultiple([ | ||
t.jsxText(spacesLeft), | ||
t.jsxExpressionContainer(t.callExpression(t.identifier(importLocal), [t.stringLiteral(id)])), | ||
t.jsxText(spacesRight) | ||
]); | ||
needI18n = true; | ||
} | ||
}, | ||
TemplateLiteral: function (path) { | ||
var _a; | ||
if (t.isCallExpression(path.parent) && | ||
((_a = path.parent.callee) === null || _a === void 0 ? void 0 : _a.name) === i18nFnName) { | ||
return; | ||
} | ||
if (zhExt.test(path.toString())) { | ||
// 处理这种情况 | ||
// <% if (data.usage === 0) { %> | ||
// ${'主要用于展示'} | ||
// <% } else if(data.usage === 1) { %> | ||
var node = path.node; | ||
var isCh_1 = false; | ||
node.quasis && | ||
node.quasis.forEach(function (item) { | ||
if (zhExt.test(item.value.raw)) { | ||
isCh_1 = true; | ||
} | ||
}); | ||
if (isCh_1) { | ||
var variables_1 = []; | ||
var i_1 = 0; | ||
var value = path | ||
.toString() | ||
.replace(/^`|`$/g, '') | ||
.replace(/\$\{([\s\S]+?)\}/g, function () { | ||
var agr = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
agr[_i] = arguments[_i]; | ||
} | ||
i_1++; | ||
variables_1.push({ | ||
id: i_1, | ||
name: agr[1] | ||
}); | ||
return "{{@".concat(i_1, "}}"); | ||
}); | ||
var id = md5Hash(value); | ||
if (noLocale(value, id, relativePath)) { | ||
return; | ||
} | ||
path.replaceWith(t.callExpression(t.identifier(importLocal), [ | ||
t.stringLiteral(id), | ||
t.objectExpression(node.expressions.map(function (item, index) { | ||
return t.objectProperty(t.stringLiteral("@".concat(index + 1)), item); | ||
})) | ||
])); | ||
needI18n = true; | ||
} | ||
} | ||
}, | ||
StringLiteral: function (path) { | ||
if (t.isTSLiteralType(path.parent)) { | ||
return; | ||
} | ||
if (t.isCallExpression(path.parent) && | ||
path.parent.callee.name === i18nFnName) { | ||
return; | ||
} | ||
if (zhExt.test(path.toString())) { | ||
var value = path.node.value.toString(); | ||
var id = md5Hash(value); | ||
if (noLocale(value, id, relativePath)) { | ||
return; | ||
} | ||
if (t.isJSXAttribute(path.parent)) { | ||
path.replaceWith(t.jsxExpressionContainer(t.callExpression(t.identifier(importLocal), [t.stringLiteral(id)]))); | ||
} | ||
else { | ||
path.replaceWith(t.callExpression(t.identifier(importLocal), [t.stringLiteral(id)])); | ||
} | ||
needI18n = true; | ||
} | ||
} | ||
} | ||
}, | ||
StringLiteral(path) { | ||
if (t.isTSLiteralType(path.parent)) { | ||
return; | ||
} | ||
if ( | ||
t.isCallExpression(path.parent) && | ||
path.parent.callee.name === i18nFnName | ||
) { | ||
return; | ||
} | ||
if (zhExt.test(path.toString())) { | ||
const value = path.node.value.toString(); | ||
const id = md5Hash(value); | ||
if (noLocale(value, id, relativePath)) { | ||
return; | ||
} | ||
if (t.isJSXAttribute(path.parent)) { | ||
path.replaceWith( | ||
t.jsxExpressionContainer( | ||
t.callExpression(t.identifier(importLocal), [t.stringLiteral(id)]) | ||
) | ||
); | ||
} else { | ||
path.replaceWith( | ||
t.callExpression(t.identifier(importLocal), [t.stringLiteral(id)]) | ||
); | ||
} | ||
needI18n = true; | ||
} | ||
}; | ||
traverse(ast, visitor); | ||
if (needI18n) { | ||
var codeRes = generate(ast, { | ||
jsescOption: { | ||
minimal: true | ||
}, | ||
decoratorsBeforeExport: true | ||
}, content); | ||
return codeRes.code; | ||
} | ||
}; | ||
traverse(ast, visitor); | ||
if (needI18n) { | ||
const codeRes = generate( | ||
ast, | ||
{ | ||
jsescOption: { | ||
minimal: true | ||
}, | ||
decoratorsBeforeExport: true | ||
}, | ||
content | ||
); | ||
return codeRes.code; | ||
} else { | ||
return content; | ||
} | ||
else { | ||
return content; | ||
} | ||
}; |
{ | ||
"name": "fis3-parser-react-i18n", | ||
"version": "0.0.23-beta.11", | ||
"version": "0.0.23-beta.12", | ||
"description": "fis3处理react国际化插件", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
10051
0
247