44 * See the accompanying LICENSE file for terms.
55 */
66
7- import * as p from " path" ;
8- import { writeFileSync } from "fs" ;
9- import { sync as mkdirpSync } from " mkdirp" ;
10- import printICUMessage from " ./print-icu-message" ;
7+ import * as p from ' path' ;
8+ import { writeFileSync } from 'fs' ;
9+ import { sync as mkdirpSync } from ' mkdirp' ;
10+ import printICUMessage from ' ./print-icu-message' ;
1111
12- const COMPONENT_NAMES = [ " FormattedMessage" , " FormattedHTMLMessage" ] ;
12+ const COMPONENT_NAMES = [ ' FormattedMessage' , ' FormattedHTMLMessage' ] ;
1313
14- const FUNCTION_NAMES = [ " defineMessages" ] ;
14+ const FUNCTION_NAMES = [ ' defineMessages' ] ;
1515
16- const DESCRIPTOR_PROPS = new Set ( [ "id" , " description" , " defaultMessage" ] ) ;
16+ const DESCRIPTOR_PROPS = new Set ( [ 'id' , ' description' , ' defaultMessage' ] ) ;
1717
18- const EXTRACTED = Symbol ( " ReactIntlExtracted" ) ;
19- const MESSAGES = Symbol ( " ReactIntlMessages" ) ;
18+ const EXTRACTED = Symbol ( ' ReactIntlExtracted' ) ;
19+ const MESSAGES = Symbol ( ' ReactIntlMessages' ) ;
2020
2121export default function ( { types :t } ) {
2222function getModuleSourceName ( opts ) {
23- return opts . moduleSourceName || " react-intl" ;
23+ return opts . moduleSourceName || ' react-intl' ;
2424}
2525
2626function evaluatePath ( path ) {
@@ -30,7 +30,7 @@ export default function({ types: t }) {
3030}
3131
3232throw path . buildCodeFrameError (
33- " [React Intl] Messages must be statically evaluate-able for extraction."
33+ ' [React Intl] Messages must be statically evaluate-able for extraction.'
3434) ;
3535}
3636
@@ -44,13 +44,13 @@ export default function({ types: t }) {
4444
4545function getMessageDescriptorValue ( path ) {
4646if ( path . isJSXExpressionContainer ( ) ) {
47- path = path . get ( " expression" ) ;
47+ path = path . get ( ' expression' ) ;
4848}
4949
5050// Always trim the Message Descriptor values.
5151const descriptorValue = evaluatePath ( path ) ;
5252
53- if ( typeof descriptorValue === " string" ) {
53+ if ( typeof descriptorValue === ' string' ) {
5454return descriptorValue . trim ( ) ;
5555}
5656
@@ -66,20 +66,20 @@ export default function({ types: t }) {
6666if (
6767isJSXSource &&
6868messagePath . isLiteral ( ) &&
69- message . indexOf ( " \\\\" ) >= 0
69+ message . indexOf ( ' \\\\' ) >= 0
7070) {
7171throw messagePath . buildCodeFrameError (
72- " [React Intl] Message failed to parse." +
73- " It looks like `\\`s were used for escaping," +
72+ ' [React Intl] Message failed to parse.' +
73+ ' It looks like `\\`s were used for escaping,' +
7474"this won't work with JSX string literals. " +
75- " Wrap with `{}`." +
76- " See: http://facebook.github.io/react/docs/jsx-gotchas.html"
75+ ' Wrap with `{}`.' +
76+ ' See: http://facebook.github.io/react/docs/jsx-gotchas.html'
7777) ;
7878}
7979
8080throw messagePath . buildCodeFrameError (
81- " [React Intl] Message failed to parse." +
82- " See: http://formatjs.io/guides/message-syntax/" +
81+ ' [React Intl] Message failed to parse.' +
82+ ' See: http://formatjs.io/guides/message-syntax/' +
8383`\n${ parseError } `
8484) ;
8585}
@@ -104,7 +104,7 @@ export default function({ types: t }) {
104104Object . keys ( descriptor ) . forEach ( key => {
105105const valuePath = descriptor [ key ] ;
106106
107- if ( key === " defaultMessage" ) {
107+ if ( key === ' defaultMessage' ) {
108108descriptor [ key ] = getICUMessageValue ( valuePath , { isJSXSource} ) ;
109109} else {
110110descriptor [ key ] = getMessageDescriptorValue ( valuePath ) ;
@@ -127,7 +127,7 @@ export default function({ types: t }) {
127127
128128if ( ! ( id && defaultMessage ) ) {
129129throw path . buildCodeFrameError (
130- " [React Intl] Message Descriptors require an `id` and `defaultMessage`."
130+ ' [React Intl] Message Descriptors require an `id` and `defaultMessage`.'
131131) ;
132132}
133133
@@ -141,18 +141,18 @@ export default function({ types: t }) {
141141) {
142142throw path . buildCodeFrameError (
143143`[React Intl] Duplicate message id: "${ id } ", ` +
144- " but the `description` and/or `defaultMessage` are different."
144+ ' but the `description` and/or `defaultMessage` are different.'
145145) ;
146146}
147147}
148148
149149if ( opts . enforceDescriptions ) {
150150if (
151151! description ||
152- ( typeof description === " object" && Object . keys ( description ) . length < 1 )
152+ ( typeof description === ' object' && Object . keys ( description ) . length < 1 )
153153) {
154154throw path . buildCodeFrameError (
155- " [React Intl] Message must have a `description`."
155+ ' [React Intl] Message must have a `description`.'
156156) ;
157157}
158158}
@@ -178,13 +178,13 @@ export default function({ types: t }) {
178178
179179function isFormatMessageCall ( path ) {
180180if ( t . isMemberExpression ( path ) ) {
181- const property = path . get ( " property" ) ;
181+ const property = path . get ( ' property' ) ;
182182
183- if ( t . isIdentifier ( property ) && property . node . name === " formatMessage" ) {
184- const object = path . get ( " object" ) ;
185- const objectProperty = object . get ( " property" ) ;
183+ if ( t . isIdentifier ( property ) && property . node . name === ' formatMessage' ) {
184+ const object = path . get ( ' object' ) ;
185+ const objectProperty = object . get ( ' property' ) ;
186186if ( t . isIdentifier ( objectProperty ) ) {
187- if ( objectProperty . node . name === " intl" ) {
187+ if ( objectProperty . node . name === ' intl' ) {
188188return true ;
189189}
190190}
@@ -216,7 +216,7 @@ export default function({ types: t }) {
216216const basename = p . basename ( filename , p . extname ( filename ) ) ;
217217const messages = file . get ( MESSAGES ) ;
218218const descriptors = [ ...messages . values ( ) ] ;
219- file . metadata [ " react-intl" ] = { messages :descriptors } ;
219+ file . metadata [ ' react-intl' ] = { messages :descriptors } ;
220220
221221if ( opts . messagesDir && descriptors . length > 0 ) {
222222// Make sure the relative path is "absolute" before
@@ -225,7 +225,7 @@ export default function({ types: t }) {
225225// Solve when the window user has symlink on the directory, because
226226// process.cwd on windows returns the symlink root,
227227// and filename (from babel) returns the original root
228- if ( process . platform === " win32" ) {
228+ if ( process . platform === ' win32' ) {
229229const { name} = p . parse ( process . cwd ( ) ) ;
230230if ( relativePath . includes ( name ) ) {
231231relativePath = relativePath . slice (
@@ -237,7 +237,7 @@ export default function({ types: t }) {
237237const messagesFilename = p . join (
238238opts . messagesDir ,
239239p . dirname ( relativePath ) ,
240- basename + " .json"
240+ basename + ' .json'
241241) ;
242242
243243const messagesFile = JSON . stringify ( descriptors , null , 2 ) ;
@@ -255,26 +255,26 @@ export default function({ types: t }) {
255255
256256const { file, opts} = state ;
257257const moduleSourceName = getModuleSourceName ( opts ) ;
258- const name = path . get ( " name" ) ;
258+ const name = path . get ( ' name' ) ;
259259
260- if ( name . referencesImport ( moduleSourceName , " FormattedPlural" ) ) {
260+ if ( name . referencesImport ( moduleSourceName , ' FormattedPlural' ) ) {
261261const warn = file . log ?file . log . warn :console . warn ;
262262warn (
263263`[React Intl] Line${ path . node . loc . start . line } : ` +
264- " Default messages are not extracted from" +
265- " <FormattedPlural>, use <FormattedMessage> instead."
264+ ' Default messages are not extracted from' +
265+ ' <FormattedPlural>, use <FormattedMessage> instead.'
266266) ;
267267
268268return ;
269269}
270270
271271if ( referencesImport ( name , moduleSourceName , COMPONENT_NAMES ) ) {
272272const attributes = path
273- . get ( " attributes" )
273+ . get ( ' attributes' )
274274. filter ( attr => attr . isJSXAttribute ( ) ) ;
275275
276276let descriptor = createMessageDescriptor (
277- attributes . map ( attr => [ attr . get ( " name" ) , attr . get ( " value" ) ] )
277+ attributes . map ( attr => [ attr . get ( ' name' ) , attr . get ( ' value' ) ] )
278278) ;
279279
280280// In order for a default message to be extracted when
@@ -296,14 +296,14 @@ export default function({ types: t }) {
296296
297297// Remove description since it's not used at runtime.
298298attributes . forEach ( attr => {
299- const ketPath = attr . get ( " name" ) ;
300- if ( getMessageDescriptorKey ( ketPath ) === " description" ) {
299+ const ketPath = attr . get ( ' name' ) ;
300+ if ( getMessageDescriptorKey ( ketPath ) === ' description' ) {
301301attr . remove ( ) ;
302302} else if (
303303opts . overrideIdFn &&
304- getMessageDescriptorKey ( ketPath ) === "id"
304+ getMessageDescriptorKey ( ketPath ) === 'id'
305305) {
306- attr . get ( " value" ) . replaceWith ( t . stringLiteral ( descriptor . id ) ) ;
306+ attr . get ( ' value' ) . replaceWith ( t . stringLiteral ( descriptor . id ) ) ;
307307}
308308} ) ;
309309
@@ -315,16 +315,16 @@ export default function({ types: t }) {
315315
316316CallExpression ( path , state ) {
317317const moduleSourceName = getModuleSourceName ( state . opts ) ;
318- const callee = path . get ( " callee" ) ;
318+ const callee = path . get ( ' callee' ) ;
319319const { opts} = state ;
320320
321321function assertObjectExpression ( node ) {
322322if ( ! ( node && node . isObjectExpression ( ) ) ) {
323323throw path . buildCodeFrameError (
324324`[React Intl] \`${ callee . node . name } ()\` must be ` +
325- " called with an object expression with values" +
326- " that are React Intl Message Descriptors, also" +
327- " defined as object expressions."
325+ ' called with an object expression with values' +
326+ ' that are React Intl Message Descriptors, also' +
327+ ' defined as object expressions.'
328328) ;
329329}
330330}
@@ -336,10 +336,10 @@ export default function({ types: t }) {
336336return ;
337337}
338338
339- const properties = messageObj . get ( " properties" ) ;
339+ const properties = messageObj . get ( ' properties' ) ;
340340
341341let descriptor = createMessageDescriptor (
342- properties . map ( prop => [ prop . get ( " key" ) , prop . get ( " value" ) ] )
342+ properties . map ( prop => [ prop . get ( ' key' ) , prop . get ( ' value' ) ] )
343343) ;
344344
345345// Evaluate the Message Descriptor values, then store it.
@@ -352,11 +352,11 @@ export default function({ types: t }) {
352352messageObj . replaceWith (
353353t . objectExpression ( [
354354t . objectProperty (
355- t . stringLiteral ( "id" ) ,
355+ t . stringLiteral ( 'id' ) ,
356356t . stringLiteral ( descriptor . id )
357357) ,
358358t . objectProperty (
359- t . stringLiteral ( " defaultMessage" ) ,
359+ t . stringLiteral ( ' defaultMessage' ) ,
360360t . stringLiteral ( descriptor . defaultMessage )
361361)
362362] )
@@ -367,18 +367,18 @@ export default function({ types: t }) {
367367}
368368
369369if ( referencesImport ( callee , moduleSourceName , FUNCTION_NAMES ) ) {
370- const messagesObj = path . get ( " arguments" ) [ 0 ] ;
370+ const messagesObj = path . get ( ' arguments' ) [ 0 ] ;
371371
372372assertObjectExpression ( messagesObj ) ;
373373
374374messagesObj
375- . get ( " properties" )
376- . map ( prop => prop . get ( " value" ) )
375+ . get ( ' properties' )
376+ . map ( prop => prop . get ( ' value' ) )
377377. forEach ( processMessageObject ) ;
378378}
379379
380380if ( isFormatMessageCall ( callee ) ) {
381- const messagesObj = path . get ( " arguments" ) [ 0 ] ;
381+ const messagesObj = path . get ( ' arguments' ) [ 0 ] ;
382382processMessageObject ( messagesObj ) ;
383383}
384384}