babel-plugin-formatjs 10.3.26 → 10.3.27

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 (52) hide show
  1. package/index.d.ts +10 -0
  2. package/index.d.ts.map +1 -0
  3. package/index.js +69 -0
  4. package/package.json +3 -3
  5. package/types.d.ts +31 -0
  6. package/types.d.ts.map +1 -0
  7. package/types.js +2 -0
  8. package/utils.d.ts +34 -0
  9. package/utils.d.ts.map +1 -0
  10. package/utils.js +152 -0
  11. package/visitors/call-expression.d.ts +6 -0
  12. package/visitors/call-expression.d.ts.map +1 -0
  13. package/visitors/call-expression.js +124 -0
  14. package/visitors/jsx-opening-element.d.ts +6 -0
  15. package/visitors/jsx-opening-element.d.ts.map +1 -0
  16. package/visitors/jsx-opening-element.js +87 -0
  17. package/BUILD +0 -90
  18. package/CHANGELOG.md +0 -1139
  19. package/index.ts +0 -88
  20. package/integration-tests/BUILD +0 -21
  21. package/integration-tests/package.json +0 -5
  22. package/integration-tests/vue/fixtures/App.vue +0 -19
  23. package/integration-tests/vue/fixtures/app.js +0 -6
  24. package/integration-tests/vue/integration.test.ts +0 -62
  25. package/tests/__snapshots__/index.test.ts.snap +0 -1246
  26. package/tests/fixtures/2663.js +0 -3
  27. package/tests/fixtures/FormattedMessage.js +0 -14
  28. package/tests/fixtures/additionalComponentNames.js +0 -15
  29. package/tests/fixtures/additionalFunctionNames.js +0 -23
  30. package/tests/fixtures/ast.js +0 -45
  31. package/tests/fixtures/defineMessage.js +0 -57
  32. package/tests/fixtures/defineMessages.js +0 -49
  33. package/tests/fixtures/descriptionsAsObjects.js +0 -18
  34. package/tests/fixtures/empty.js +0 -8
  35. package/tests/fixtures/extractFromFormatMessageCall.js +0 -47
  36. package/tests/fixtures/extractFromFormatMessageCallStateless.js +0 -46
  37. package/tests/fixtures/extractSourceLocation.js +0 -8
  38. package/tests/fixtures/formatMessageCall.js +0 -38
  39. package/tests/fixtures/icuSyntax.js +0 -18
  40. package/tests/fixtures/idInterpolationPattern.js +0 -40
  41. package/tests/fixtures/inline.js +0 -26
  42. package/tests/fixtures/overrideIdFn.js +0 -48
  43. package/tests/fixtures/preserveWhitespace.js +0 -79
  44. package/tests/fixtures/removeDefaultMessage.js +0 -36
  45. package/tests/fixtures/skipExtractionFormattedMessage.js +0 -12
  46. package/tests/fixtures/templateLiteral.js +0 -21
  47. package/tests/index.test.ts +0 -221
  48. package/tsconfig.json +0 -5
  49. package/types.ts +0 -46
  50. package/utils.ts +0 -226
  51. package/visitors/call-expression.ts +0 -208
  52. package/visitors/jsx-opening-element.ts +0 -147
package/index.d.ts ADDED
@@ -0,0 +1,10 @@
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 ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["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 ADDED
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_ID_INTERPOLATION_PATTERN = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const helper_plugin_utils_1 = require("@babel/helper-plugin-utils");
6
+ const plugin_syntax_jsx_1 = tslib_1.__importDefault(require("@babel/plugin-syntax-jsx"));
7
+ const jsx_opening_element_1 = require("./visitors/jsx-opening-element");
8
+ const 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)((api, options) => {
12
+ api.assertVersion(7);
13
+ if (!options.idInterpolationPattern) {
14
+ options.idInterpolationPattern = exports.DEFAULT_ID_INTERPOLATION_PATTERN;
15
+ }
16
+ const { pragma } = options;
17
+ const componentNames = new Set(options.additionalComponentNames);
18
+ componentNames.add('FormattedMessage');
19
+ const 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() {
26
+ this.componentNames = Array.from(componentNames);
27
+ this.functionNames = Array.from(functionNames);
28
+ },
29
+ visitor: {
30
+ Program: {
31
+ enter(path) {
32
+ this.messages = [];
33
+ this.meta = {};
34
+ if (!pragma) {
35
+ return;
36
+ }
37
+ for (const { leadingComments } of path.node.body) {
38
+ if (!leadingComments) {
39
+ continue;
40
+ }
41
+ const pragmaLineNode = leadingComments.find(c => c.value.includes(pragma));
42
+ if (!pragmaLineNode) {
43
+ continue;
44
+ }
45
+ pragmaLineNode.value
46
+ .split(pragma)[1]
47
+ .trim()
48
+ .split(/\s+/g)
49
+ .forEach(kv => {
50
+ const [k, v] = kv.split(':');
51
+ this.meta[k] = v;
52
+ });
53
+ }
54
+ },
55
+ exit(_, { opts: _opts, file: { opts: { filename }, }, }) {
56
+ const opts = _opts;
57
+ if (typeof opts?.onMetaExtracted === 'function') {
58
+ opts.onMetaExtracted(filename || '', this.meta);
59
+ }
60
+ if (typeof opts?.onMsgExtracted === 'function') {
61
+ opts.onMsgExtracted(filename || '', this.messages);
62
+ }
63
+ },
64
+ },
65
+ JSXOpeningElement: jsx_opening_element_1.visitor,
66
+ CallExpression: call_expression_1.visitor,
67
+ },
68
+ };
69
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "babel-plugin-formatjs",
3
- "version": "10.3.26",
3
+ "version": "10.3.27",
4
4
  "description": "Extracts string messages for translation from modules that use formatjs.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -16,8 +16,8 @@
16
16
  "@babel/plugin-syntax-jsx": "7",
17
17
  "@babel/traverse": "7",
18
18
  "@babel/types": "^7.12.11",
19
- "@formatjs/icu-messageformat-parser": "2.1.5",
20
- "@formatjs/ts-transformer": "3.9.10",
19
+ "@formatjs/icu-messageformat-parser": "2.1.6",
20
+ "@formatjs/ts-transformer": "3.9.11",
21
21
  "@types/babel__core": "^7.1.7",
22
22
  "@types/babel__helper-plugin-utils": "^7.10.0",
23
23
  "@types/babel__traverse": "^7.1.7",
package/types.d.ts ADDED
@@ -0,0 +1,31 @@
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 ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["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 ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/utils.d.ts ADDED
@@ -0,0 +1,34 @@
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 ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["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 ADDED
@@ -0,0 +1,152 @@
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
+ const icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
5
+ const ts_transformer_1 = require("@formatjs/ts-transformer");
6
+ const DESCRIPTOR_PROPS = new Set([
7
+ 'id',
8
+ 'description',
9
+ 'defaultMessage',
10
+ ]);
11
+ function evaluatePath(path) {
12
+ const evaluated = path.evaluate();
13
+ if (evaluated.confident) {
14
+ return evaluated.value;
15
+ }
16
+ throw path.buildCodeFrameError('[React Intl] Messages must be statically evaluate-able for extraction.');
17
+ }
18
+ function getMessageDescriptorKey(path) {
19
+ if (path.isIdentifier() || path.isJSXIdentifier()) {
20
+ return path.node.name;
21
+ }
22
+ return evaluatePath(path);
23
+ }
24
+ exports.getMessageDescriptorKey = getMessageDescriptorKey;
25
+ function getMessageDescriptorValue(path, isMessageNode) {
26
+ if (!path) {
27
+ return '';
28
+ }
29
+ if (path.isJSXExpressionContainer()) {
30
+ // If this is already compiled, no need to recompiled it
31
+ if (isMessageNode && path.get('expression').isArrayExpression()) {
32
+ return '';
33
+ }
34
+ path = path.get('expression');
35
+ }
36
+ // Always trim the Message Descriptor values.
37
+ const descriptorValue = evaluatePath(path);
38
+ return descriptorValue;
39
+ }
40
+ function createMessageDescriptor(propPaths) {
41
+ return propPaths.reduce((hash, [keyPath, valuePath]) => {
42
+ const key = getMessageDescriptorKey(keyPath);
43
+ if (DESCRIPTOR_PROPS.has(key)) {
44
+ hash[key] = valuePath;
45
+ }
46
+ return hash;
47
+ }, {
48
+ id: undefined,
49
+ defaultMessage: undefined,
50
+ description: undefined,
51
+ });
52
+ }
53
+ exports.createMessageDescriptor = createMessageDescriptor;
54
+ function evaluateMessageDescriptor(descriptorPath, isJSXSource = false, filename, idInterpolationPattern, overrideIdFn, preserveWhitespace) {
55
+ let id = getMessageDescriptorValue(descriptorPath.id);
56
+ const defaultMessage = getICUMessageValue(descriptorPath.defaultMessage, {
57
+ isJSXSource,
58
+ }, preserveWhitespace);
59
+ const description = getMessageDescriptorValue(descriptorPath.description);
60
+ if (overrideIdFn) {
61
+ id = overrideIdFn(id, defaultMessage, description, filename);
62
+ }
63
+ else if (!id && idInterpolationPattern && defaultMessage) {
64
+ id = (0, ts_transformer_1.interpolateName)({ resourcePath: filename }, idInterpolationPattern, {
65
+ content: description
66
+ ? `${defaultMessage}#${description}`
67
+ : defaultMessage,
68
+ });
69
+ }
70
+ const descriptor = {
71
+ id,
72
+ };
73
+ if (description) {
74
+ descriptor.description = description;
75
+ }
76
+ if (defaultMessage) {
77
+ descriptor.defaultMessage = defaultMessage;
78
+ }
79
+ return descriptor;
80
+ }
81
+ exports.evaluateMessageDescriptor = evaluateMessageDescriptor;
82
+ function getICUMessageValue(messagePath, { isJSXSource = false } = {}, preserveWhitespace) {
83
+ if (!messagePath) {
84
+ return '';
85
+ }
86
+ let message = getMessageDescriptorValue(messagePath, true);
87
+ if (!preserveWhitespace) {
88
+ message = message.trim().replace(/\s+/gm, ' ');
89
+ }
90
+ try {
91
+ (0, icu_messageformat_parser_1.parse)(message);
92
+ }
93
+ catch (parseError) {
94
+ if (isJSXSource &&
95
+ messagePath.isLiteral() &&
96
+ message.indexOf('\\\\') >= 0) {
97
+ throw messagePath.buildCodeFrameError('[React Intl] Message failed to parse. ' +
98
+ 'It looks like `\\`s were used for escaping, ' +
99
+ "this won't work with JSX string literals. " +
100
+ 'Wrap with `{}`. ' +
101
+ 'See: http://facebook.github.io/react/docs/jsx-gotchas.html');
102
+ }
103
+ throw messagePath.buildCodeFrameError('[React Intl] Message failed to parse. ' +
104
+ 'See: https://formatjs.io/docs/core-concepts/icu-syntax' +
105
+ `\n${parseError}`);
106
+ }
107
+ return message;
108
+ }
109
+ const EXTRACTED = Symbol('FormatJSExtracted');
110
+ /**
111
+ * Tag a node as extracted
112
+ * Store this in the node itself so that multiple passes work. Specifically
113
+ * if we remove `description` in the 1st pass, 2nd pass will fail since
114
+ * it expect `description` to be there.
115
+ * HACK: We store this in the node instance since this persists across
116
+ * multiple plugin runs
117
+ * @param path
118
+ */
119
+ function tagAsExtracted(path) {
120
+ path.node[EXTRACTED] = true;
121
+ }
122
+ exports.tagAsExtracted = tagAsExtracted;
123
+ /**
124
+ * Check if a node was extracted
125
+ * @param path
126
+ */
127
+ function wasExtracted(path) {
128
+ return !!path.node[EXTRACTED];
129
+ }
130
+ exports.wasExtracted = wasExtracted;
131
+ /**
132
+ * Store a message in our global messages
133
+ * @param messageDescriptor
134
+ * @param path
135
+ * @param opts
136
+ * @param filename
137
+ * @param messages
138
+ */
139
+ function storeMessage({ id, description, defaultMessage }, path, { extractSourceLocation }, filename, messages) {
140
+ if (!id && !defaultMessage) {
141
+ throw path.buildCodeFrameError('[React Intl] Message Descriptors require an `id` or `defaultMessage`.');
142
+ }
143
+ let loc = {};
144
+ if (extractSourceLocation) {
145
+ loc = {
146
+ file: filename,
147
+ ...path.node.loc,
148
+ };
149
+ }
150
+ messages.push({ id, description, defaultMessage, ...loc });
151
+ }
152
+ exports.storeMessage = storeMessage;
@@ -0,0 +1,6 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call-expression.d.ts","sourceRoot":"","sources":["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"}
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.visitor = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const t = tslib_1.__importStar(require("@babel/types"));
6
+ const utils_1 = require("../utils");
7
+ const 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] \`${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(name => callee.isIdentifier({ name }))) {
15
+ return true;
16
+ }
17
+ if (callee.isMemberExpression()) {
18
+ const property = callee.get('property');
19
+ return !!functionNames.find(name => property.isIdentifier({ name }));
20
+ }
21
+ return false;
22
+ }
23
+ function getMessagesObjectFromExpression(nodePath) {
24
+ let 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
+ const visitor = function (path, { opts, file: { opts: { filename }, }, }) {
33
+ const { overrideIdFn, idInterpolationPattern, removeDefaultMessage, ast, preserveWhitespace, } = opts;
34
+ if ((0, utils_1.wasExtracted)(path)) {
35
+ return;
36
+ }
37
+ const { messages, functionNames } = this;
38
+ const callee = path.get('callee');
39
+ const args = path.get('arguments');
40
+ /**
41
+ * Process MessageDescriptor
42
+ * @param messageDescriptor Message Descriptor
43
+ */
44
+ function processMessageObject(messageDescriptor) {
45
+ assertObjectExpression(messageDescriptor, callee);
46
+ const properties = messageDescriptor.get('properties');
47
+ const descriptorPath = (0, utils_1.createMessageDescriptor)(properties.map(prop => [prop.get('key'), prop.get('value')]));
48
+ // If the message is already compiled, don't re-compile it
49
+ if (descriptorPath.defaultMessage?.isArrayExpression()) {
50
+ return;
51
+ }
52
+ // Evaluate the Message Descriptor values, then store it.
53
+ const descriptor = (0, utils_1.evaluateMessageDescriptor)(descriptorPath, false, filename || undefined, idInterpolationPattern, overrideIdFn, preserveWhitespace);
54
+ (0, utils_1.storeMessage)(descriptor, messageDescriptor, opts, filename || undefined, messages);
55
+ const firstProp = properties[0];
56
+ const defaultMessageProp = properties.find(prop => {
57
+ const keyProp = prop.get('key');
58
+ return (keyProp.isIdentifier({ name: 'defaultMessage' }) ||
59
+ keyProp.isStringLiteral({ value: 'defaultMessage' }));
60
+ });
61
+ const idProp = properties.find(prop => {
62
+ const keyProp = prop.get('key');
63
+ return (keyProp.isIdentifier({ name: 'id' }) ||
64
+ keyProp.isStringLiteral({ value: 'id' }));
65
+ });
66
+ // Insert ID potentially 1st before removing nodes
67
+ if (idProp) {
68
+ idProp.get('value').replaceWith(t.stringLiteral(descriptor.id));
69
+ }
70
+ else {
71
+ firstProp.insertBefore(t.objectProperty(t.identifier('id'), t.stringLiteral(descriptor.id)));
72
+ }
73
+ // Remove description
74
+ properties
75
+ .find(prop => {
76
+ const keyProp = prop.get('key');
77
+ return (keyProp.isIdentifier({ name: 'description' }) ||
78
+ keyProp.isStringLiteral({ value: 'description' }));
79
+ })
80
+ ?.remove();
81
+ // Pre-parse or remove defaultMessage
82
+ if (defaultMessageProp) {
83
+ if (removeDefaultMessage) {
84
+ defaultMessageProp?.remove();
85
+ }
86
+ else if (descriptor.defaultMessage) {
87
+ const valueProp = defaultMessageProp.get('value');
88
+ if (ast) {
89
+ valueProp.replaceWithSourceString(JSON.stringify((0, icu_messageformat_parser_1.parse)(descriptor.defaultMessage)));
90
+ }
91
+ else {
92
+ valueProp.replaceWith(t.stringLiteral(descriptor.defaultMessage));
93
+ }
94
+ }
95
+ }
96
+ (0, utils_1.tagAsExtracted)(path);
97
+ }
98
+ // Check that this is `defineMessages` call
99
+ if (callee.isIdentifier({ name: 'defineMessages' }) ||
100
+ callee.isIdentifier({ name: 'defineMessage' })) {
101
+ const firstArgument = args[0];
102
+ const messagesObj = getMessagesObjectFromExpression(firstArgument);
103
+ assertObjectExpression(messagesObj, callee);
104
+ if (callee.isIdentifier({ name: 'defineMessage' })) {
105
+ processMessageObject(messagesObj);
106
+ }
107
+ else {
108
+ const properties = messagesObj.get('properties');
109
+ if (Array.isArray(properties)) {
110
+ properties
111
+ .map(prop => prop.get('value'))
112
+ .forEach(processMessageObject);
113
+ }
114
+ }
115
+ }
116
+ // Check that this is `intl.formatMessage` call
117
+ if (isFormatMessageCall(callee, functionNames)) {
118
+ const messageDescriptor = args[0];
119
+ if (messageDescriptor.isObjectExpression()) {
120
+ processMessageObject(messageDescriptor);
121
+ }
122
+ }
123
+ };
124
+ exports.visitor = visitor;
@@ -0,0 +1,6 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-opening-element.d.ts","sourceRoot":"","sources":["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"}
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.visitor = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const t = tslib_1.__importStar(require("@babel/types"));
6
+ const icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
7
+ const utils_1 = require("../utils");
8
+ const visitor = function (path, { opts, file: { opts: { filename }, }, }) {
9
+ const { removeDefaultMessage, idInterpolationPattern, overrideIdFn, ast, preserveWhitespace, } = opts;
10
+ const { componentNames, messages } = this;
11
+ if ((0, utils_1.wasExtracted)(path)) {
12
+ return;
13
+ }
14
+ const name = path.get('name');
15
+ if (!componentNames.find(n => name.isJSXIdentifier({ name: n }))) {
16
+ return;
17
+ }
18
+ const attributes = path
19
+ .get('attributes')
20
+ .filter(attr => attr.isJSXAttribute());
21
+ const descriptorPath = (0, utils_1.createMessageDescriptor)(attributes.map(attr => [
22
+ attr.get('name'),
23
+ attr.get('value'),
24
+ ]));
25
+ // In order for a default message to be extracted when
26
+ // declaring a JSX element, it must be done with standard
27
+ // `key=value` attributes. But it's completely valid to
28
+ // write `<FormattedMessage {...descriptor} />`, because it will be
29
+ // skipped here and extracted elsewhere. The descriptor will
30
+ // be extracted only (storeMessage) if a `defaultMessage` prop.
31
+ if (!descriptorPath.defaultMessage) {
32
+ return;
33
+ }
34
+ // Evaluate the Message Descriptor values in a JSX
35
+ // context, then store it.
36
+ const descriptor = (0, utils_1.evaluateMessageDescriptor)(descriptorPath, true, filename || undefined, idInterpolationPattern, overrideIdFn, preserveWhitespace);
37
+ (0, utils_1.storeMessage)(descriptor, path, opts, filename || undefined, messages);
38
+ let idAttr;
39
+ let descriptionAttr;
40
+ let defaultMessageAttr;
41
+ const firstAttr = attributes[0];
42
+ for (const attr of attributes) {
43
+ if (!attr.isJSXAttribute()) {
44
+ continue;
45
+ }
46
+ switch ((0, utils_1.getMessageDescriptorKey)(attr.get('name'))) {
47
+ case 'description':
48
+ descriptionAttr = attr;
49
+ break;
50
+ case 'defaultMessage':
51
+ defaultMessageAttr = attr;
52
+ break;
53
+ case 'id':
54
+ idAttr = attr;
55
+ break;
56
+ }
57
+ }
58
+ // Insert ID before removing node to prevent null node insertBefore
59
+ if (overrideIdFn || (descriptor.id && idInterpolationPattern)) {
60
+ if (idAttr) {
61
+ idAttr.get('value').replaceWith(t.stringLiteral(descriptor.id));
62
+ }
63
+ else if (firstAttr) {
64
+ firstAttr.insertBefore(t.jsxAttribute(t.jsxIdentifier('id'), t.stringLiteral(descriptor.id)));
65
+ }
66
+ }
67
+ if (descriptionAttr) {
68
+ descriptionAttr.remove();
69
+ }
70
+ if (defaultMessageAttr) {
71
+ if (removeDefaultMessage) {
72
+ defaultMessageAttr.remove();
73
+ }
74
+ else if (ast && descriptor.defaultMessage) {
75
+ defaultMessageAttr
76
+ .get('value')
77
+ .replaceWith(t.jsxExpressionContainer(t.nullLiteral()));
78
+ const valueAttr = defaultMessageAttr.get('value');
79
+ valueAttr
80
+ .get('expression')
81
+ .replaceWithSourceString(JSON.stringify((0, icu_messageformat_parser_1.parse)(descriptor.defaultMessage)));
82
+ }
83
+ }
84
+ // Tag the AST node so we don't try to extract it twice.
85
+ (0, utils_1.tagAsExtracted)(path);
86
+ };
87
+ exports.visitor = visitor;
package/BUILD DELETED
@@ -1,90 +0,0 @@
1
- load("@aspect_bazel_lib//lib:write_source_files.bzl", "write_source_files")
2
- load("@aspect_rules_js//npm/private:npm_package.bzl", "npm_package")
3
- load("@npm//:defs.bzl", "npm_link_all_packages")
4
- load("//tools:index.bzl", "check_format", "package_json_test", "ts_compile_node")
5
- load("//tools:jest.bzl", "jest_test")
6
-
7
- npm_link_all_packages(name = "node_modules")
8
-
9
- PACKAGE_NAME = "babel-plugin-formatjs"
10
-
11
- npm_package(
12
- name = PACKAGE_NAME,
13
- srcs = [
14
- "LICENSE.md",
15
- "README.md",
16
- "package.json",
17
- ":dist",
18
- ],
19
- package = PACKAGE_NAME,
20
- visibility = ["//visibility:public"],
21
- )
22
-
23
- SRCS = glob(
24
- ["**/*.ts"],
25
- exclude = ["tests/**/*"],
26
- )
27
-
28
- SRC_DEPS = [
29
- "//:node_modules/@babel/core",
30
- "//:node_modules/@babel/helper-plugin-utils",
31
- "//:node_modules/@babel/plugin-syntax-jsx",
32
- "//:node_modules/@babel/traverse",
33
- "//:node_modules/@babel/types",
34
- ":node_modules/@formatjs/icu-messageformat-parser",
35
- ":node_modules/@formatjs/ts-transformer",
36
- "//:node_modules/@types/babel__core",
37
- "//:node_modules/@types/babel__helper-plugin-utils",
38
- "//:node_modules/@types/babel__traverse",
39
- ]
40
-
41
- ts_compile_node(
42
- name = "dist",
43
- srcs = SRCS,
44
- deps = SRC_DEPS,
45
- )
46
-
47
- jest_test(
48
- name = "unit",
49
- srcs = SRCS + glob(
50
- [
51
- "tests/**/*.ts",
52
- "tests/**/*.tsx",
53
- "tests/**/*.js",
54
- "tests/**/*.json",
55
- ],
56
- exclude = ["tests/vue/**/*"],
57
- ),
58
- snapshots = glob([
59
- "tests/**/*.snap",
60
- ]),
61
- deps = [
62
- "//:node_modules/@babel/preset-env",
63
- "//:node_modules/@babel/preset-react",
64
- "//:node_modules/@types/node",
65
- ] + SRC_DEPS,
66
- )
67
-
68
- package_json_test(
69
- name = "package_json_test",
70
- deps = SRC_DEPS,
71
- )
72
-
73
- write_source_files(
74
- name = "tsconfig_json",
75
- files = {"tsconfig.json": "//tools:tsconfig.golden.json"},
76
- )
77
-
78
- check_format(
79
- name = "prettier",
80
- srcs = glob(
81
- [
82
- "**/*",
83
- ],
84
- exclude = [
85
- "CHANGELOG.md",
86
- "options.ts",
87
- "tests/__snapshots__/*",
88
- ],
89
- ),
90
- )