diff --git a/index.ts b/index.ts index 44dab49..5af0422 100644 --- a/index.ts +++ b/index.ts @@ -14,6 +14,20 @@ function isMethodCall( ); } +function isExportMethodCall( + el: ts.Declaration, + methodName: string, +): el is ts.ExportAssignment { + return ( + ts.isExportAssignment(el) && + !!el.expression && + ts.isCallExpression(el.expression) && + !!el.expression.expression && + ts.isIdentifier(el.expression.expression) && + el.expression.expression.text === methodName + ); +} + /** * Represents a react-intl message descriptor */ @@ -122,9 +136,9 @@ function extractMessagesForNode( function forAllVarDecls( node: ts.Node, - cb: (decl: ts.VariableDeclaration) => void, + cb: (decl: ts.VariableDeclaration | ts.ExportAssignment) => void, ) { - if (ts.isVariableDeclaration(node)) { + if (ts.isVariableDeclaration(node) || ts.isExportAssignment(node)) { cb(node); } else { ts.forEachChild(node, (n) => forAllVarDecls(n, cb)); @@ -168,6 +182,16 @@ function findMethodCallsWithName( const declMessages = extractMessagesForNode(nodeProps, extractMessages); messages = messages.concat(declMessages); } + } else if (isExportMethodCall(decl, methodName)) { + if ( + decl.expression && + ts.isCallExpression(decl.expression) && + decl.expression.arguments.length + ) { + const nodeProps = decl.expression.arguments[0]; + const declMessages = extractMessagesForNode(nodeProps, extractMessages); + messages = messages.concat(declMessages); + } } }); return messages; diff --git a/lib/index.js b/lib/index.js index 1dc3c33..7f60e12 100644 --- a/lib/index.js +++ b/lib/index.js @@ -9,6 +9,14 @@ function isMethodCall(el, methodName) { ts.isIdentifier(el.initializer.expression) && el.initializer.expression.text === methodName); } +function isExportMethodCall(el, methodName) { + return (ts.isExportAssignment(el) && + !!el.expression && + ts.isCallExpression(el.expression) && + !!el.expression.expression && + ts.isIdentifier(el.expression.expression) && + el.expression.expression.text === methodName); +} // sets `target[key] = value`, but only if it is a legal Message key function copyIfMessageKey(target, key, value) { switch (key) { @@ -76,7 +84,7 @@ function extractMessagesForNode(node, extractMessages) { return res; } function forAllVarDecls(node, cb) { - if (ts.isVariableDeclaration(node)) { + if (ts.isVariableDeclaration(node) || ts.isExportAssignment(node)) { cb(node); } else { @@ -111,6 +119,15 @@ function findMethodCallsWithName(sourceFile, methodName, extractMessages) { messages = messages.concat(declMessages); } } + else if (isExportMethodCall(decl, methodName)) { + if (decl.expression && + ts.isCallExpression(decl.expression) && + decl.expression.arguments.length) { + var nodeProps = decl.expression.arguments[0]; + var declMessages = extractMessagesForNode(nodeProps, extractMessages); + messages = messages.concat(declMessages); + } + } }); return messages; } diff --git a/test/app/defineMessagesExportDefault.ts b/test/app/defineMessagesExportDefault.ts new file mode 100644 index 0000000..306c184 --- /dev/null +++ b/test/app/defineMessagesExportDefault.ts @@ -0,0 +1,23 @@ +import { defineMessages } from 'react-intl' + +// NB not a variable declaration; should be ignored + +export default defineMessages({ + intro: { + id: 'intro.hello', + defaultMessage: "Hello world" + }, + "title": { + "id": 'app.title', + "defaultMessage": "Hello", + "description": "A description for title" + }, + multiLineLiteral: { + id: 'hello.world', + defaultMessage: `Hello, {scope, plural, + =person {human} + =planet {world} + other {thing} + }!` + } +}); diff --git a/test/index.js b/test/index.js index 6bbee4f..112939c 100644 --- a/test/index.js +++ b/test/index.js @@ -70,6 +70,32 @@ test("defineMessages() should only work with variable declaration", (t) => { t.deepEqual(res, expected); }); +test("defineMessages() should with export default", (t) => { + var content = fs.readFileSync(__dirname + "/app/defineMessagesExportDefault.ts"); + + var res = p(content.toString()); + + var expected = [ + { + id: "intro.hello", + defaultMessage: "Hello world", + }, + { + id: "app.title", + defaultMessage: "Hello", + description: "A description for title", + }, + { + id: "hello.world", + defaultMessage: "Hello, {scope, plural,\n =person {human}\n =planet {world}\n other {thing}\n }!", + } + ]; + + t.is(res.length, 3); + + t.deepEqual(res, expected); +}); + test(" should work with StatelessComponent", (t) => { var content = fs.readFileSync(__dirname + "/app/statelessComponent.tsx");