diff --git a/package-lock.json b/package-lock.json index 4fe7eea..462f758 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,6 @@ "@babel/plugin-transform-class-properties": "^7.25.0", "@babel/traverse": "^7.26.0", "babel-project-relative-import": "^2.0.1", - "lodash": "^4.17.21", "randchinese": "^1.0.0" }, "bin": { @@ -6111,12 +6110,6 @@ "node": ">=8" } }, - "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", - "license": "MIT" - }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", diff --git a/package.json b/package.json index 4b2e543..390fb1b 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,6 @@ "@babel/plugin-transform-class-properties": "^7.25.0", "@babel/traverse": "^7.26.0", "babel-project-relative-import": "^2.0.1", - "lodash": "^4.17.21", "randchinese": "^1.0.0" }, "jest": { diff --git a/src/frozen-asts.js b/src/frozen-asts.js index 0ad574c..b2ba4ac 100644 --- a/src/frozen-asts.js +++ b/src/frozen-asts.js @@ -1,8 +1,8 @@ -const babylon = require('@babel/parser'); +const parser = require('@babel/parser'); // TODO: Use line numbers to move the two imports to separate lines -const i18nextImportStatement = babylon.parse('import i18n from \'i18next\';\n', { sourceType: 'module' }).program.body[0]; -const kImportStatement = babylon.parse('import k from \'~/i18n/keys\';\n', { sourceType: 'module' }).program.body[0]; +const i18nextImportStatement = parser.parse('import i18n from \'i18next\';\n', { sourceType: 'module' }).program.body[0]; +const kImportStatement = parser.parse('import k from \'~/i18n/keys\';\n', { sourceType: 'module' }).program.body[0]; module.exports = { i18nextImportStatement, diff --git a/src/plugin-helpers.js b/src/plugin-helpers.js index 4db0a91..11fe755 100644 --- a/src/plugin-helpers.js +++ b/src/plugin-helpers.js @@ -1,25 +1,24 @@ -const babel = require('@babel/core'); -const _ = require('lodash'); +const { types: t } = require('@babel/core'); const { getUniqueKeyFromFreeText, } = require('./lut'); +const BLACKLISTED_JSX_ATTRIBUTES = [ + // React router + 'path', 'from', 'to', 'href', 'as', + // Inline style + 'style', 'className', 'color', + // Code + 'dangerouslySetInnerHTML', 'src', +]; + // Dont extract value for Literals under this attribute const isBlacklistedForJsxAttribute = (path) => { - const blacklistedJsxAttributes = [ - // React router - 'path', 'from', 'to', 'href', 'as', - // Inline style - 'style', 'className', 'color', - // Code - 'dangerouslySetInnerHTML', 'src', - ]; const jsxAttributeParent = path.findParent(p => p.isJSXAttribute()); if (!jsxAttributeParent) return false; - const name = _.get(jsxAttributeParent, 'node.name.name'); - if (blacklistedJsxAttributes.includes(name)) return true; - return false; + const name = jsxAttributeParent.node.name && jsxAttributeParent.node.name.name; + return BLACKLISTED_JSX_ATTRIBUTES.includes(name); }; @@ -34,13 +33,12 @@ const handleConditionalExpressions = (path) => { // Check for blacklist if (isBlacklistedForJsxAttribute(path)) return; - const coreValue = _.get(path, 'node.value', '').trim(); + const coreValue = (path.node.value || '').trim(); if (!coreValue.length) return; const kValue = getUniqueKeyFromFreeText(coreValue); - // TODO: OPTIMIZATION: Use quasi quotes to optimize this const srcString = `i18n.t(k.${kValue})`; - if (babel.types.isJSXAttribute(path.parent)) { + if (t.isJSXAttribute(path.parent)) { // TODO: The next line does not parse // path.replaceWithSourceString(`{${srcString}}`); } else { @@ -51,4 +49,5 @@ const handleConditionalExpressions = (path) => { module.exports = { isBlacklistedForJsxAttribute, handleConditionalExpressions, + BLACKLISTED_JSX_ATTRIBUTES, }; diff --git a/src/plugin.js b/src/plugin.js index f924b17..0e93fcf 100644 --- a/src/plugin.js +++ b/src/plugin.js @@ -1,5 +1,3 @@ -const _ = require('lodash'); - const { i18nextImportStatement, kImportStatement, @@ -15,6 +13,8 @@ const { handleConditionalExpressions, } = require('./plugin-helpers'); +const cloneDeep = (obj) => JSON.parse(JSON.stringify(obj)); + const handleStringLiteral = (path, table, key) => { const { value } = path.node; if (!table[key]) table[key] = {}; @@ -46,7 +46,6 @@ module.exports = ({ types: t }) => ({ Object.keys(this.state).forEach((key) => { if (this.state[key].valid && this.state[key].pairs) { this.state[key].pairs.forEach(({ path, value }) => { - // TODO: OPTIMIZATION: Use quasi quotes to optimize this const kValue = getUniqueKeyFromFreeText(value); path.replaceWithSourceString(`i18n.t(k.${kValue})`); }); @@ -55,10 +54,10 @@ module.exports = ({ types: t }) => ({ // Do not add imports if there is no replaceable text // in this file if (LutManager.getUniqueKeyFromFreeTextNumCalls > 0) { - if (!this.alreadyImportedK) programPath.node.body.unshift(_.cloneDeep(kImportStatement)); + if (!this.alreadyImportedK) programPath.node.body.unshift(cloneDeep(kImportStatement)); if (!this.alreadyImportedi18n) { programPath.node.body - .unshift(_.cloneDeep(i18nextImportStatement)); + .unshift(cloneDeep(i18nextImportStatement)); } } }, @@ -79,7 +78,7 @@ module.exports = ({ types: t }) => ({ // Only extract the value of identifiers // who are children of some JSX element if (path.findParent(p => p.isJSXElement())) { - this.state[path.node.name] = _.merge(this.state[path.node.name], { valid: true }); + this.state[path.node.name] = { ...this.state[path.node.name], valid: true }; } }, }, @@ -91,21 +90,20 @@ module.exports = ({ types: t }) => ({ if (!firstJsxParent) return; // Ignore CSS strings - if (_.get(firstJsxParent, 'node.openingElement.name.name') === 'style') return; + if (firstJsxParent.node.openingElement?.name?.name === 'style') return; if (isBlacklistedForJsxAttribute(path)) return; const { expressions, quasis } = path.node; expressions.forEach((expression) => { const key = expression.name; - this.state[key] = _.merge(this.state[key], { valid: true }); + this.state[key] = { ...this.state[key], valid: true }; }); quasis.forEach((templateElement, index) => { const coreValue = templateElement.value.raw.trim(); if (coreValue.length) { const qPath = path.get('quasis')[index]; const kValue = getUniqueKeyFromFreeText(coreValue); - // TODO: OPTIMIZATION: Use quasi quotes to optimize this // TODO: Replace the path instead of modifying the raw qPath.node.value.raw = qPath.node.value.raw.replace(coreValue, `\${i18n.t(k.${kValue})}`); qPath.node.value.cooked = qPath.node.value.cooked.replace(coreValue, `\${i18n.t(k.${kValue})}`); @@ -115,15 +113,14 @@ module.exports = ({ types: t }) => ({ }, AssignmentExpression: { enter(path) { - // TODO: Explore the reason behind crash - const key = _.get(path, 'node.left.name', _.get(path, 'node.left.property.name')); + const key = path.node.left.name || (path.node.left.property && path.node.left.property.name); if (!key) return; extractValueAndUpdateTable(t, this.state, path.get('right'), key); }, }, ObjectProperty: { enter(path) { - const key = _.get(path, 'node.key.name'); + const key = path.node.key && path.node.key.name; if (!key) return; // Check for blacklist @@ -134,8 +131,7 @@ module.exports = ({ types: t }) => ({ }, VariableDeclarator: { enter(path) { - // TODO: Explore the reason behind crash - const key = _.get(path, 'node.id.name'); + const key = path.node.id && path.node.id.name; if (!key) return; // Check for blacklist @@ -146,10 +142,9 @@ module.exports = ({ types: t }) => ({ }, JSXText: { enter(path) { - const coreValue = _.get(path, 'node.value', '').trim(); + const coreValue = (path.node.value || '').trim(); if (!coreValue.length) return; const kValue = getUniqueKeyFromFreeText(coreValue); - // TODO: OPTIMIZATION: Use quasi quotes to optimize this path.node.value = path.node.value.replace(coreValue, `{i18n.t(k.${kValue})}`); }, }, diff --git a/src/used-plugins.js b/src/used-plugins.js index f293046..c8c226c 100644 --- a/src/used-plugins.js +++ b/src/used-plugins.js @@ -1,6 +1,6 @@ const parserPlugins = [ 'jsx', - 'classProperties', // '@babel/plugin-transform-class-properties', + 'classProperties', 'flow', ];