babel-plugin-formatjs 10.3.25 → 10.3.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/BUILD +90 -0
  2. package/CHANGELOG.md +1139 -0
  3. package/LICENSE.md +0 -0
  4. package/README.md +0 -0
  5. package/global.d.ts +0 -0
  6. package/index.ts +88 -0
  7. package/integration-tests/BUILD +21 -0
  8. package/integration-tests/package.json +5 -0
  9. package/integration-tests/vue/fixtures/App.vue +19 -0
  10. package/integration-tests/vue/fixtures/app.js +6 -0
  11. package/integration-tests/vue/integration.test.ts +62 -0
  12. package/package.json +5 -4
  13. package/tests/__snapshots__/index.test.ts.snap +1246 -0
  14. package/tests/fixtures/2663.js +3 -0
  15. package/tests/fixtures/FormattedMessage.js +14 -0
  16. package/tests/fixtures/additionalComponentNames.js +15 -0
  17. package/tests/fixtures/additionalFunctionNames.js +23 -0
  18. package/tests/fixtures/ast.js +45 -0
  19. package/tests/fixtures/defineMessage.js +57 -0
  20. package/tests/fixtures/defineMessages.js +49 -0
  21. package/tests/fixtures/descriptionsAsObjects.js +18 -0
  22. package/tests/fixtures/empty.js +8 -0
  23. package/tests/fixtures/extractFromFormatMessageCall.js +47 -0
  24. package/tests/fixtures/extractFromFormatMessageCallStateless.js +46 -0
  25. package/tests/fixtures/extractSourceLocation.js +8 -0
  26. package/tests/fixtures/formatMessageCall.js +38 -0
  27. package/tests/fixtures/icuSyntax.js +18 -0
  28. package/tests/fixtures/idInterpolationPattern.js +40 -0
  29. package/tests/fixtures/inline.js +26 -0
  30. package/tests/fixtures/overrideIdFn.js +48 -0
  31. package/tests/fixtures/preserveWhitespace.js +79 -0
  32. package/tests/fixtures/removeDefaultMessage.js +36 -0
  33. package/tests/fixtures/skipExtractionFormattedMessage.js +12 -0
  34. package/tests/fixtures/templateLiteral.js +21 -0
  35. package/tests/index.test.ts +221 -0
  36. package/tsconfig.json +5 -0
  37. package/types.ts +46 -0
  38. package/utils.ts +226 -0
  39. package/visitors/call-expression.ts +208 -0
  40. package/visitors/jsx-opening-element.ts +147 -0
  41. package/index.d.ts +0 -10
  42. package/index.d.ts.map +0 -1
  43. package/index.js +0 -74
  44. package/types.d.ts +0 -31
  45. package/types.d.ts.map +0 -1
  46. package/types.js +0 -2
  47. package/utils.d.ts +0 -34
  48. package/utils.d.ts.map +0 -1
  49. package/utils.js +0 -155
  50. package/visitors/call-expression.d.ts +0 -6
  51. package/visitors/call-expression.d.ts.map +0 -1
  52. package/visitors/call-expression.js +0 -127
  53. package/visitors/jsx-opening-element.d.ts +0 -6
  54. package/visitors/jsx-opening-element.d.ts.map +0 -1
  55. package/visitors/jsx-opening-element.js +0 -89
@@ -0,0 +1,147 @@
1
+ import {NodePath, PluginPass} from '@babel/core'
2
+
3
+ import {Options, State} from '../types'
4
+ import * as t from '@babel/types'
5
+ import {VisitNodeFunction} from '@babel/traverse'
6
+ import {parse} from '@formatjs/icu-messageformat-parser'
7
+ import {
8
+ createMessageDescriptor,
9
+ evaluateMessageDescriptor,
10
+ getMessageDescriptorKey,
11
+ storeMessage,
12
+ tagAsExtracted,
13
+ wasExtracted,
14
+ } from '../utils'
15
+
16
+ export const visitor: VisitNodeFunction<
17
+ PluginPass & State,
18
+ t.JSXOpeningElement
19
+ > = function (
20
+ path,
21
+ {
22
+ opts,
23
+ file: {
24
+ opts: {filename},
25
+ },
26
+ }
27
+ ) {
28
+ const {
29
+ removeDefaultMessage,
30
+ idInterpolationPattern,
31
+ overrideIdFn,
32
+ ast,
33
+ preserveWhitespace,
34
+ } = opts as Options
35
+
36
+ const {componentNames, messages} = this
37
+ if (wasExtracted(path)) {
38
+ return
39
+ }
40
+
41
+ const name = path.get('name')
42
+
43
+ if (!componentNames.find(n => name.isJSXIdentifier({name: n}))) {
44
+ return
45
+ }
46
+
47
+ const attributes = path
48
+ .get('attributes')
49
+ .filter(attr => attr.isJSXAttribute())
50
+
51
+ const descriptorPath = createMessageDescriptor(
52
+ attributes.map(attr => [
53
+ attr.get('name') as NodePath<t.JSXIdentifier>,
54
+ attr.get('value') as
55
+ | NodePath<t.StringLiteral>
56
+ | NodePath<t.JSXExpressionContainer>,
57
+ ])
58
+ )
59
+
60
+ // In order for a default message to be extracted when
61
+ // declaring a JSX element, it must be done with standard
62
+ // `key=value` attributes. But it's completely valid to
63
+ // write `<FormattedMessage {...descriptor} />`, because it will be
64
+ // skipped here and extracted elsewhere. The descriptor will
65
+ // be extracted only (storeMessage) if a `defaultMessage` prop.
66
+ if (!descriptorPath.defaultMessage) {
67
+ return
68
+ }
69
+
70
+ // Evaluate the Message Descriptor values in a JSX
71
+ // context, then store it.
72
+ const descriptor = evaluateMessageDescriptor(
73
+ descriptorPath,
74
+ true,
75
+ filename || undefined,
76
+ idInterpolationPattern,
77
+ overrideIdFn,
78
+ preserveWhitespace
79
+ )
80
+
81
+ storeMessage(
82
+ descriptor,
83
+ path,
84
+ opts as Options,
85
+ filename || undefined,
86
+ messages
87
+ )
88
+
89
+ let idAttr: NodePath<t.JSXAttribute> | undefined
90
+ let descriptionAttr: NodePath<t.JSXAttribute> | undefined
91
+ let defaultMessageAttr: NodePath<t.JSXAttribute> | undefined
92
+ const firstAttr = attributes[0]
93
+ for (const attr of attributes) {
94
+ if (!attr.isJSXAttribute()) {
95
+ continue
96
+ }
97
+ switch (
98
+ getMessageDescriptorKey((attr as NodePath<t.JSXAttribute>).get('name'))
99
+ ) {
100
+ case 'description':
101
+ descriptionAttr = attr
102
+ break
103
+ case 'defaultMessage':
104
+ defaultMessageAttr = attr
105
+ break
106
+ case 'id':
107
+ idAttr = attr
108
+ break
109
+ }
110
+ }
111
+
112
+ // Insert ID before removing node to prevent null node insertBefore
113
+ if (overrideIdFn || (descriptor.id && idInterpolationPattern)) {
114
+ if (idAttr) {
115
+ idAttr.get('value').replaceWith(t.stringLiteral(descriptor.id))
116
+ } else if (firstAttr) {
117
+ firstAttr.insertBefore(
118
+ t.jsxAttribute(t.jsxIdentifier('id'), t.stringLiteral(descriptor.id))
119
+ )
120
+ }
121
+ }
122
+
123
+ if (descriptionAttr) {
124
+ descriptionAttr.remove()
125
+ }
126
+
127
+ if (defaultMessageAttr) {
128
+ if (removeDefaultMessage) {
129
+ defaultMessageAttr.remove()
130
+ } else if (ast && descriptor.defaultMessage) {
131
+ defaultMessageAttr
132
+ .get('value')
133
+ .replaceWith(t.jsxExpressionContainer(t.nullLiteral()))
134
+ const valueAttr = defaultMessageAttr.get(
135
+ 'value'
136
+ ) as NodePath<t.JSXExpressionContainer>
137
+ valueAttr
138
+ .get('expression')
139
+ .replaceWithSourceString(
140
+ JSON.stringify(parse(descriptor.defaultMessage))
141
+ )
142
+ }
143
+ }
144
+
145
+ // Tag the AST node so we don't try to extract it twice.
146
+ tagAsExtracted(path)
147
+ }
package/index.d.ts DELETED
@@ -1,10 +0,0 @@
1
- import { PluginObj, PluginPass } from '@babel/core';
2
- import { ExtractedMessageDescriptor, Options } from './types';
3
- export declare type ExtractionResult<M = Record<string, string>> = {
4
- messages: ExtractedMessageDescriptor[];
5
- meta: M;
6
- };
7
- export declare const DEFAULT_ID_INTERPOLATION_PATTERN = "[sha512:contenthash:base64:6]";
8
- declare const _default: (api: object, options: Options | null | undefined, dirname: string) => PluginObj<PluginPass>;
9
- export default _default;
10
- //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/babel-plugin-formatjs/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,SAAS,EAAE,UAAU,EAAC,MAAM,aAAa,CAAA;AAEjD,OAAO,EAAC,0BAA0B,EAAE,OAAO,EAAQ,MAAM,SAAS,CAAA;AAIlE,oBAAY,gBAAgB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI;IACzD,QAAQ,EAAE,0BAA0B,EAAE,CAAA;IACtC,IAAI,EAAE,CAAC,CAAA;CACR,CAAA;AAED,eAAO,MAAM,gCAAgC,kCAAkC,CAAA;;AAG/E,wBAwEE"}
package/index.js DELETED
@@ -1,74 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DEFAULT_ID_INTERPOLATION_PATTERN = void 0;
4
- var tslib_1 = require("tslib");
5
- var helper_plugin_utils_1 = require("@babel/helper-plugin-utils");
6
- var plugin_syntax_jsx_1 = (0, tslib_1.__importDefault)(require("@babel/plugin-syntax-jsx"));
7
- var jsx_opening_element_1 = require("./visitors/jsx-opening-element");
8
- var call_expression_1 = require("./visitors/call-expression");
9
- exports.DEFAULT_ID_INTERPOLATION_PATTERN = '[sha512:contenthash:base64:6]';
10
- // @ts-expect-error PluginPass doesn't allow custom state but it actually does
11
- exports.default = (0, helper_plugin_utils_1.declare)(function (api, options) {
12
- api.assertVersion(7);
13
- if (!options.idInterpolationPattern) {
14
- options.idInterpolationPattern = exports.DEFAULT_ID_INTERPOLATION_PATTERN;
15
- }
16
- var pragma = options.pragma;
17
- var componentNames = new Set(options.additionalComponentNames);
18
- componentNames.add('FormattedMessage');
19
- var functionNames = new Set(options.additionalFunctionNames);
20
- functionNames.add('formatMessage');
21
- // Vue
22
- functionNames.add('$formatMessage');
23
- return {
24
- inherits: plugin_syntax_jsx_1.default,
25
- pre: function () {
26
- this.componentNames = Array.from(componentNames);
27
- this.functionNames = Array.from(functionNames);
28
- },
29
- visitor: {
30
- Program: {
31
- enter: function (path) {
32
- var _this = this;
33
- this.messages = [];
34
- this.meta = {};
35
- if (!pragma) {
36
- return;
37
- }
38
- for (var _i = 0, _a = path.node.body; _i < _a.length; _i++) {
39
- var leadingComments = _a[_i].leadingComments;
40
- if (!leadingComments) {
41
- continue;
42
- }
43
- var pragmaLineNode = leadingComments.find(function (c) {
44
- return c.value.includes(pragma);
45
- });
46
- if (!pragmaLineNode) {
47
- continue;
48
- }
49
- pragmaLineNode.value
50
- .split(pragma)[1]
51
- .trim()
52
- .split(/\s+/g)
53
- .forEach(function (kv) {
54
- var _a = kv.split(':'), k = _a[0], v = _a[1];
55
- _this.meta[k] = v;
56
- });
57
- }
58
- },
59
- exit: function (_, _a) {
60
- var _opts = _a.opts, filename = _a.file.opts.filename;
61
- var opts = _opts;
62
- if (typeof (opts === null || opts === void 0 ? void 0 : opts.onMetaExtracted) === 'function') {
63
- opts.onMetaExtracted(filename || '', this.meta);
64
- }
65
- if (typeof (opts === null || opts === void 0 ? void 0 : opts.onMsgExtracted) === 'function') {
66
- opts.onMsgExtracted(filename || '', this.messages);
67
- }
68
- },
69
- },
70
- JSXOpeningElement: jsx_opening_element_1.visitor,
71
- CallExpression: call_expression_1.visitor,
72
- },
73
- };
74
- });
package/types.d.ts DELETED
@@ -1,31 +0,0 @@
1
- import { NodePath } from '@babel/core';
2
- import { JSXExpressionContainer, SourceLocation, StringLiteral } from '@babel/types';
3
- export interface MessageDescriptor {
4
- id: string;
5
- defaultMessage?: string;
6
- description?: string;
7
- }
8
- export interface State {
9
- messages: ExtractedMessageDescriptor[];
10
- meta: Record<string, string>;
11
- componentNames: string[];
12
- functionNames: string[];
13
- }
14
- export declare type ExtractedMessageDescriptor = MessageDescriptor & Partial<SourceLocation> & {
15
- file?: string;
16
- };
17
- export declare type MessageDescriptorPath = Record<keyof MessageDescriptor, NodePath<StringLiteral> | NodePath<JSXExpressionContainer> | undefined>;
18
- export interface Options {
19
- overrideIdFn?: (id?: string, defaultMessage?: string, description?: string, filePath?: string) => string;
20
- onMsgExtracted?: (filePath: string, msgs: MessageDescriptor[]) => void;
21
- onMetaExtracted?: (filePath: string, meta: Record<string, string>) => void;
22
- idInterpolationPattern?: string;
23
- removeDefaultMessage?: boolean;
24
- additionalComponentNames?: string[];
25
- additionalFunctionNames?: string[];
26
- pragma?: string;
27
- extractSourceLocation?: boolean;
28
- ast?: boolean;
29
- preserveWhitespace?: boolean;
30
- }
31
- //# sourceMappingURL=types.d.ts.map
package/types.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../packages/babel-plugin-formatjs/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAA;AACpC,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,aAAa,EACd,MAAM,cAAc,CAAA;AAErB,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,KAAK;IACpB,QAAQ,EAAE,0BAA0B,EAAE,CAAA;IACtC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,aAAa,EAAE,MAAM,EAAE,CAAA;CACxB;AAED,oBAAY,0BAA0B,GAAG,iBAAiB,GACxD,OAAO,CAAC,cAAc,CAAC,GAAG;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAC,CAAA;AAE3C,oBAAY,qBAAqB,GAAG,MAAM,CACxC,MAAM,iBAAiB,EACvB,QAAQ,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC,sBAAsB,CAAC,GAAG,SAAS,CACvE,CAAA;AAED,MAAM,WAAW,OAAO;IACtB,YAAY,CAAC,EAAE,CACb,EAAE,CAAC,EAAE,MAAM,EACX,cAAc,CAAC,EAAE,MAAM,EACvB,WAAW,CAAC,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,MAAM,KACd,MAAM,CAAA;IACX,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,IAAI,CAAA;IACtE,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAA;IAC1E,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,wBAAwB,CAAC,EAAE,MAAM,EAAE,CAAA;IACnC,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAA;IAClC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B"}
package/types.js DELETED
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
package/utils.d.ts DELETED
@@ -1,34 +0,0 @@
1
- import * as t from '@babel/types';
2
- import { Options, ExtractedMessageDescriptor, MessageDescriptor, MessageDescriptorPath } from './types';
3
- import { NodePath } from '@babel/core';
4
- export declare function getMessageDescriptorKey(path: NodePath<any>): string;
5
- export declare function createMessageDescriptor(propPaths: [
6
- NodePath<t.JSXIdentifier> | NodePath<t.Identifier>,
7
- NodePath<t.StringLiteral> | NodePath<t.JSXExpressionContainer>
8
- ][]): MessageDescriptorPath;
9
- export declare function evaluateMessageDescriptor(descriptorPath: MessageDescriptorPath, isJSXSource: boolean | undefined, filename: string | undefined, idInterpolationPattern?: string, overrideIdFn?: Options['overrideIdFn'], preserveWhitespace?: Options['preserveWhitespace']): MessageDescriptor;
10
- /**
11
- * Tag a node as extracted
12
- * Store this in the node itself so that multiple passes work. Specifically
13
- * if we remove `description` in the 1st pass, 2nd pass will fail since
14
- * it expect `description` to be there.
15
- * HACK: We store this in the node instance since this persists across
16
- * multiple plugin runs
17
- * @param path
18
- */
19
- export declare function tagAsExtracted(path: NodePath<any>): void;
20
- /**
21
- * Check if a node was extracted
22
- * @param path
23
- */
24
- export declare function wasExtracted(path: NodePath<any>): boolean;
25
- /**
26
- * Store a message in our global messages
27
- * @param messageDescriptor
28
- * @param path
29
- * @param opts
30
- * @param filename
31
- * @param messages
32
- */
33
- export declare function storeMessage({ id, description, defaultMessage }: MessageDescriptor, path: NodePath<any>, { extractSourceLocation }: Options, filename: string | undefined, messages: ExtractedMessageDescriptor[]): void;
34
- //# sourceMappingURL=utils.d.ts.map
package/utils.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../packages/babel-plugin-formatjs/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,cAAc,CAAA;AAIjC,OAAO,EACL,OAAO,EACP,0BAA0B,EAC1B,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,SAAS,CAAA;AAChB,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAA;AAmBpC,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,UAM1D;AA0BD,wBAAgB,uBAAuB,CACrC,SAAS,EAAE;IACT,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;IAClD,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,sBAAsB,CAAC;CAC/D,EAAE,GACF,qBAAqB,CAmBvB;AAED,wBAAgB,yBAAyB,CACvC,cAAc,EAAE,qBAAqB,EACrC,WAAW,qBAAQ,EACnB,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,sBAAsB,CAAC,EAAE,MAAM,EAC/B,YAAY,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,EACtC,kBAAkB,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,qBAqCnD;AA6CD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,QAEjD;AACD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,WAE/C;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,EAAC,EAAE,EAAE,WAAW,EAAE,cAAc,EAAC,EAAE,iBAAiB,EACpD,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,EACnB,EAAC,qBAAqB,EAAC,EAAE,OAAO,EAEhC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,QAAQ,EAAE,0BAA0B,EAAE,QAgBvC"}
package/utils.js DELETED
@@ -1,155 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.storeMessage = exports.wasExtracted = exports.tagAsExtracted = exports.evaluateMessageDescriptor = exports.createMessageDescriptor = exports.getMessageDescriptorKey = void 0;
4
- var tslib_1 = require("tslib");
5
- var icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
6
- var ts_transformer_1 = require("@formatjs/ts-transformer");
7
- var DESCRIPTOR_PROPS = new Set([
8
- 'id',
9
- 'description',
10
- 'defaultMessage',
11
- ]);
12
- function evaluatePath(path) {
13
- var evaluated = path.evaluate();
14
- if (evaluated.confident) {
15
- return evaluated.value;
16
- }
17
- throw path.buildCodeFrameError('[React Intl] Messages must be statically evaluate-able for extraction.');
18
- }
19
- function getMessageDescriptorKey(path) {
20
- if (path.isIdentifier() || path.isJSXIdentifier()) {
21
- return path.node.name;
22
- }
23
- return evaluatePath(path);
24
- }
25
- exports.getMessageDescriptorKey = getMessageDescriptorKey;
26
- function getMessageDescriptorValue(path, isMessageNode) {
27
- if (!path) {
28
- return '';
29
- }
30
- if (path.isJSXExpressionContainer()) {
31
- // If this is already compiled, no need to recompiled it
32
- if (isMessageNode && path.get('expression').isArrayExpression()) {
33
- return '';
34
- }
35
- path = path.get('expression');
36
- }
37
- // Always trim the Message Descriptor values.
38
- var descriptorValue = evaluatePath(path);
39
- return descriptorValue;
40
- }
41
- function createMessageDescriptor(propPaths) {
42
- return propPaths.reduce(function (hash, _a) {
43
- var keyPath = _a[0], valuePath = _a[1];
44
- var key = getMessageDescriptorKey(keyPath);
45
- if (DESCRIPTOR_PROPS.has(key)) {
46
- hash[key] = valuePath;
47
- }
48
- return hash;
49
- }, {
50
- id: undefined,
51
- defaultMessage: undefined,
52
- description: undefined,
53
- });
54
- }
55
- exports.createMessageDescriptor = createMessageDescriptor;
56
- function evaluateMessageDescriptor(descriptorPath, isJSXSource, filename, idInterpolationPattern, overrideIdFn, preserveWhitespace) {
57
- if (isJSXSource === void 0) { isJSXSource = false; }
58
- var id = getMessageDescriptorValue(descriptorPath.id);
59
- var defaultMessage = getICUMessageValue(descriptorPath.defaultMessage, {
60
- isJSXSource: isJSXSource,
61
- }, preserveWhitespace);
62
- var description = getMessageDescriptorValue(descriptorPath.description);
63
- if (overrideIdFn) {
64
- id = overrideIdFn(id, defaultMessage, description, filename);
65
- }
66
- else if (!id && idInterpolationPattern && defaultMessage) {
67
- id = (0, ts_transformer_1.interpolateName)({ resourcePath: filename }, idInterpolationPattern, {
68
- content: description
69
- ? "".concat(defaultMessage, "#").concat(description)
70
- : defaultMessage,
71
- });
72
- }
73
- var descriptor = {
74
- id: id,
75
- };
76
- if (description) {
77
- descriptor.description = description;
78
- }
79
- if (defaultMessage) {
80
- descriptor.defaultMessage = defaultMessage;
81
- }
82
- return descriptor;
83
- }
84
- exports.evaluateMessageDescriptor = evaluateMessageDescriptor;
85
- function getICUMessageValue(messagePath, _a, preserveWhitespace) {
86
- var _b = _a === void 0 ? {} : _a, _c = _b.isJSXSource, isJSXSource = _c === void 0 ? false : _c;
87
- if (!messagePath) {
88
- return '';
89
- }
90
- var message = getMessageDescriptorValue(messagePath, true);
91
- if (!preserveWhitespace) {
92
- message = message.trim().replace(/\s+/gm, ' ');
93
- }
94
- try {
95
- (0, icu_messageformat_parser_1.parse)(message);
96
- }
97
- catch (parseError) {
98
- if (isJSXSource &&
99
- messagePath.isLiteral() &&
100
- message.indexOf('\\\\') >= 0) {
101
- throw messagePath.buildCodeFrameError('[React Intl] Message failed to parse. ' +
102
- 'It looks like `\\`s were used for escaping, ' +
103
- "this won't work with JSX string literals. " +
104
- 'Wrap with `{}`. ' +
105
- 'See: http://facebook.github.io/react/docs/jsx-gotchas.html');
106
- }
107
- throw messagePath.buildCodeFrameError('[React Intl] Message failed to parse. ' +
108
- 'See: https://formatjs.io/docs/core-concepts/icu-syntax' +
109
- "\n".concat(parseError));
110
- }
111
- return message;
112
- }
113
- var EXTRACTED = Symbol('FormatJSExtracted');
114
- /**
115
- * Tag a node as extracted
116
- * Store this in the node itself so that multiple passes work. Specifically
117
- * if we remove `description` in the 1st pass, 2nd pass will fail since
118
- * it expect `description` to be there.
119
- * HACK: We store this in the node instance since this persists across
120
- * multiple plugin runs
121
- * @param path
122
- */
123
- function tagAsExtracted(path) {
124
- path.node[EXTRACTED] = true;
125
- }
126
- exports.tagAsExtracted = tagAsExtracted;
127
- /**
128
- * Check if a node was extracted
129
- * @param path
130
- */
131
- function wasExtracted(path) {
132
- return !!path.node[EXTRACTED];
133
- }
134
- exports.wasExtracted = wasExtracted;
135
- /**
136
- * Store a message in our global messages
137
- * @param messageDescriptor
138
- * @param path
139
- * @param opts
140
- * @param filename
141
- * @param messages
142
- */
143
- function storeMessage(_a, path, _b, filename, messages) {
144
- var id = _a.id, description = _a.description, defaultMessage = _a.defaultMessage;
145
- var extractSourceLocation = _b.extractSourceLocation;
146
- if (!id && !defaultMessage) {
147
- throw path.buildCodeFrameError('[React Intl] Message Descriptors require an `id` or `defaultMessage`.');
148
- }
149
- var loc = {};
150
- if (extractSourceLocation) {
151
- loc = (0, tslib_1.__assign)({ file: filename }, path.node.loc);
152
- }
153
- messages.push((0, tslib_1.__assign)({ id: id, description: description, defaultMessage: defaultMessage }, loc));
154
- }
155
- exports.storeMessage = storeMessage;
@@ -1,6 +0,0 @@
1
- import { PluginPass } from '@babel/core';
2
- import * as t from '@babel/types';
3
- import { State } from '../types';
4
- import { VisitNodeFunction } from '@babel/traverse';
5
- export declare const visitor: VisitNodeFunction<PluginPass & State, t.CallExpression>;
6
- //# sourceMappingURL=call-expression.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"call-expression.d.ts","sourceRoot":"","sources":["../../../../../../packages/babel-plugin-formatjs/visitors/call-expression.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,UAAU,EAAC,MAAM,aAAa,CAAA;AAChD,OAAO,KAAK,CAAC,MAAM,cAAc,CAAA;AACjC,OAAO,EAAU,KAAK,EAAC,MAAM,UAAU,CAAA;AACvC,OAAO,EAAC,iBAAiB,EAAC,MAAM,iBAAiB,CAAA;AAoDjD,eAAO,MAAM,OAAO,EAAE,iBAAiB,CAAC,UAAU,GAAG,KAAK,EAAE,CAAC,CAAC,cAAc,CAwJzE,CAAA"}
@@ -1,127 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.visitor = void 0;
4
- var tslib_1 = require("tslib");
5
- var t = (0, tslib_1.__importStar)(require("@babel/types"));
6
- var utils_1 = require("../utils");
7
- var icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
8
- function assertObjectExpression(path, callee) {
9
- if (!path || !path.isObjectExpression()) {
10
- throw path.buildCodeFrameError("[React Intl] `".concat(callee.get('property').node.name, "()` must be called with an object expression with values that are React Intl Message Descriptors, also defined as object expressions."));
11
- }
12
- }
13
- function isFormatMessageCall(callee, functionNames) {
14
- if (functionNames.find(function (name) { return callee.isIdentifier({ name: name }); })) {
15
- return true;
16
- }
17
- if (callee.isMemberExpression()) {
18
- var property_1 = callee.get('property');
19
- return !!functionNames.find(function (name) { return property_1.isIdentifier({ name: name }); });
20
- }
21
- return false;
22
- }
23
- function getMessagesObjectFromExpression(nodePath) {
24
- var currentPath = nodePath;
25
- while (t.isTSAsExpression(currentPath.node) ||
26
- t.isTSTypeAssertion(currentPath.node) ||
27
- t.isTypeCastExpression(currentPath.node)) {
28
- currentPath = currentPath.get('expression');
29
- }
30
- return currentPath;
31
- }
32
- var visitor = function (path, _a) {
33
- var opts = _a.opts, filename = _a.file.opts.filename;
34
- var _b = opts, overrideIdFn = _b.overrideIdFn, idInterpolationPattern = _b.idInterpolationPattern, removeDefaultMessage = _b.removeDefaultMessage, ast = _b.ast, preserveWhitespace = _b.preserveWhitespace;
35
- if ((0, utils_1.wasExtracted)(path)) {
36
- return;
37
- }
38
- var _c = this, messages = _c.messages, functionNames = _c.functionNames;
39
- var callee = path.get('callee');
40
- var args = path.get('arguments');
41
- /**
42
- * Process MessageDescriptor
43
- * @param messageDescriptor Message Descriptor
44
- */
45
- function processMessageObject(messageDescriptor) {
46
- var _a, _b;
47
- assertObjectExpression(messageDescriptor, callee);
48
- var properties = messageDescriptor.get('properties');
49
- var descriptorPath = (0, utils_1.createMessageDescriptor)(properties.map(function (prop) {
50
- return [prop.get('key'), prop.get('value')];
51
- }));
52
- // If the message is already compiled, don't re-compile it
53
- if ((_a = descriptorPath.defaultMessage) === null || _a === void 0 ? void 0 : _a.isArrayExpression()) {
54
- return;
55
- }
56
- // Evaluate the Message Descriptor values, then store it.
57
- var descriptor = (0, utils_1.evaluateMessageDescriptor)(descriptorPath, false, filename || undefined, idInterpolationPattern, overrideIdFn, preserveWhitespace);
58
- (0, utils_1.storeMessage)(descriptor, messageDescriptor, opts, filename || undefined, messages);
59
- var firstProp = properties[0];
60
- var defaultMessageProp = properties.find(function (prop) {
61
- var keyProp = prop.get('key');
62
- return (keyProp.isIdentifier({ name: 'defaultMessage' }) ||
63
- keyProp.isStringLiteral({ value: 'defaultMessage' }));
64
- });
65
- var idProp = properties.find(function (prop) {
66
- var keyProp = prop.get('key');
67
- return (keyProp.isIdentifier({ name: 'id' }) ||
68
- keyProp.isStringLiteral({ value: 'id' }));
69
- });
70
- // Insert ID potentially 1st before removing nodes
71
- if (idProp) {
72
- idProp.get('value').replaceWith(t.stringLiteral(descriptor.id));
73
- }
74
- else {
75
- firstProp.insertBefore(t.objectProperty(t.identifier('id'), t.stringLiteral(descriptor.id)));
76
- }
77
- // Remove description
78
- (_b = properties
79
- .find(function (prop) {
80
- var keyProp = prop.get('key');
81
- return (keyProp.isIdentifier({ name: 'description' }) ||
82
- keyProp.isStringLiteral({ value: 'description' }));
83
- })) === null || _b === void 0 ? void 0 : _b.remove();
84
- // Pre-parse or remove defaultMessage
85
- if (defaultMessageProp) {
86
- if (removeDefaultMessage) {
87
- defaultMessageProp === null || defaultMessageProp === void 0 ? void 0 : defaultMessageProp.remove();
88
- }
89
- else if (descriptor.defaultMessage) {
90
- var valueProp = defaultMessageProp.get('value');
91
- if (ast) {
92
- valueProp.replaceWithSourceString(JSON.stringify((0, icu_messageformat_parser_1.parse)(descriptor.defaultMessage)));
93
- }
94
- else {
95
- valueProp.replaceWith(t.stringLiteral(descriptor.defaultMessage));
96
- }
97
- }
98
- }
99
- (0, utils_1.tagAsExtracted)(path);
100
- }
101
- // Check that this is `defineMessages` call
102
- if (callee.isIdentifier({ name: 'defineMessages' }) ||
103
- callee.isIdentifier({ name: 'defineMessage' })) {
104
- var firstArgument = args[0];
105
- var messagesObj = getMessagesObjectFromExpression(firstArgument);
106
- assertObjectExpression(messagesObj, callee);
107
- if (callee.isIdentifier({ name: 'defineMessage' })) {
108
- processMessageObject(messagesObj);
109
- }
110
- else {
111
- var properties = messagesObj.get('properties');
112
- if (Array.isArray(properties)) {
113
- properties
114
- .map(function (prop) { return prop.get('value'); })
115
- .forEach(processMessageObject);
116
- }
117
- }
118
- }
119
- // Check that this is `intl.formatMessage` call
120
- if (isFormatMessageCall(callee, functionNames)) {
121
- var messageDescriptor = args[0];
122
- if (messageDescriptor.isObjectExpression()) {
123
- processMessageObject(messageDescriptor);
124
- }
125
- }
126
- };
127
- exports.visitor = visitor;
@@ -1,6 +0,0 @@
1
- import { PluginPass } from '@babel/core';
2
- import { State } from '../types';
3
- import * as t from '@babel/types';
4
- import { VisitNodeFunction } from '@babel/traverse';
5
- export declare const visitor: VisitNodeFunction<PluginPass & State, t.JSXOpeningElement>;
6
- //# sourceMappingURL=jsx-opening-element.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jsx-opening-element.d.ts","sourceRoot":"","sources":["../../../../../../packages/babel-plugin-formatjs/visitors/jsx-opening-element.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,UAAU,EAAC,MAAM,aAAa,CAAA;AAEhD,OAAO,EAAU,KAAK,EAAC,MAAM,UAAU,CAAA;AACvC,OAAO,KAAK,CAAC,MAAM,cAAc,CAAA;AACjC,OAAO,EAAC,iBAAiB,EAAC,MAAM,iBAAiB,CAAA;AAWjD,eAAO,MAAM,OAAO,EAAE,iBAAiB,CACrC,UAAU,GAAG,KAAK,EAClB,CAAC,CAAC,iBAAiB,CAiIpB,CAAA"}