diff --git a/src/extractFromCode.js b/src/extractFromCode.js index 42622bb..faf64c8 100644 --- a/src/extractFromCode.js +++ b/src/extractFromCode.js @@ -3,20 +3,37 @@ import traverse from 'babel-traverse'; const noInformationTypes = ['CallExpression', 'Identifier', 'MemberExpression']; -function getKey(node) { +function getKeys(node) { if (node.type === 'StringLiteral') { - return node.value; + return [node.value]; } else if (node.type === 'BinaryExpression' && node.operator === '+') { - return getKey(node.left) + getKey(node.right); + const left = getKeys(node.left); + const right = getKeys(node.right); + if (left.length > 1 || right.length > 1) { + console.warn('Unsupported multiple keys for binary expression, keys skipped.'); // TODO + } + return [left[0] + right[0]]; } else if (node.type === 'TemplateLiteral') { - return node.quasis.map(quasi => quasi.value.cooked).join('*'); + return [node.quasis.map(quasi => quasi.value.cooked).join('*')]; + } else if (node.type === 'ConditionalExpression') { + return [...getKeys(node.consequent), ...getKeys(node.alternate)]; + } else if (node.type === 'LogicalExpression') { + switch (node.operator) { + case '&&': + return [...getKeys(node.right)]; + case '||': + return [...getKeys(node.left), ...getKeys(node.right)]; + default: + console.warn(`unsupported logicalExpression's operator: ${node.operator}`); + return [null]; + } } else if (noInformationTypes.includes(node.type)) { - return '*'; // We can't extract anything. + return ['*']; // We can't extract anything. } console.warn(`Unsupported node: ${node.type}`); - return null; + return [null]; } const commentRegExp = /i18n-extract (.+)/; @@ -81,16 +98,18 @@ export default function extractFromCode(code, options = {}) { const { callee: { name, type } } = node; if ((type === 'Identifier' && name === marker) || path.get('callee').matchesPattern(marker)) { - const key = getKey( + const foundKeys = getKeys( keyLoc < 0 ? node.arguments[node.arguments.length + keyLoc] : node.arguments[keyLoc], ); - if (key) { - keys.push({ - key, - loc: node.loc, - }); - } + foundKeys.forEach(key => { + if (key) { + keys.push({ + key, + loc: node.loc, + }); + } + }); } }, }); diff --git a/src/extractFromCode.spec.js b/src/extractFromCode.spec.js index 2b25d62..47df61a 100644 --- a/src/extractFromCode.spec.js +++ b/src/extractFromCode.spec.js @@ -646,4 +646,160 @@ describe('#extractFromCode()', () => { ); }); }); + + describe('ternary operator', () => { + it('should parse ternary operator', () => { + const keys = extractFromCode(getCode('ternaryOperator.js')); + + assert.deepEqual( + [ + { + key: '*', + loc: { + end: { + column: 23, + line: 8, + }, + start: { + column: 0, + line: 8, + }, + }, + }, + { + key: 'bar', + loc: { + end: { + column: 23, + line: 8, + }, + start: { + column: 0, + line: 8, + }, + }, + }, + { + key: '*', + loc: { + end: { + column: 50, + line: 11, + }, + start: { + column: 0, + line: 11, + }, + }, + }, + { + key: 'baz', + loc: { + end: { + column: 50, + line: 11, + }, + start: { + column: 0, + line: 11, + }, + }, + }, + { + key: 'bar', + loc: { + end: { + column: 50, + line: 11, + }, + start: { + column: 0, + line: 11, + }, + }, + }, + ], + keys, + 'Should return the good keys.', + ); + }); + }); + + describe('logical expression', () => { + it('should parse logical expressions', () => { + const keys = extractFromCode(getCode('logicalExpression.js')); + + assert.deepEqual( + [ + { + key: 'bar', + loc: { + end: { + column: 18, + line: 8, + }, + start: { + column: 0, + line: 8, + }, + }, + }, + { + key: '*', + loc: { + end: { + column: 18, + line: 11, + }, + start: { + column: 0, + line: 11, + }, + }, + }, + { + key: 'baz', + loc: { + end: { + column: 18, + line: 11, + }, + start: { + column: 0, + line: 11, + }, + }, + }, + { + key: 'bar', + loc: { + end: { + column: 27, + line: 14, + }, + start: { + column: 0, + line: 14, + }, + }, + }, + { + key: 'baz', + loc: { + end: { + column: 27, + line: 14, + }, + start: { + column: 0, + line: 14, + }, + }, + }, + ], + keys, + 'Should return the good keys.', + ); + }); + }); }); diff --git a/src/extractFromCodeFixtures/logicalExpression.js b/src/extractFromCodeFixtures/logicalExpression.js new file mode 100644 index 0000000..c6e85c2 --- /dev/null +++ b/src/extractFromCodeFixtures/logicalExpression.js @@ -0,0 +1,14 @@ +/* eslint-disable */ + +import i18n from 'i18n'; + +const foo = true; + +// && +i18n(foo && 'bar'); + +// || +i18n(foo || 'baz'); + +// mixed +i18n('bar' || foo && 'baz'); \ No newline at end of file diff --git a/src/extractFromCodeFixtures/ternaryOperator.js b/src/extractFromCodeFixtures/ternaryOperator.js new file mode 100644 index 0000000..d48bb15 --- /dev/null +++ b/src/extractFromCodeFixtures/ternaryOperator.js @@ -0,0 +1,11 @@ +/* eslint-disable */ + +import i18n from 'i18n'; + +const foo = 'bar'; + +// simple +i18n(foo ? foo : 'bar'); + +// nested +i18n(foo ? (foo.length > 1 ? foo : 'baz') : 'bar'); \ No newline at end of file