babel-plugin-formatjs 10.5.41 → 11.0.1
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.
- package/index.d.ts +1 -1
- package/index.js +13 -15
- package/package.json +4 -3
- package/types.js +1 -2
- package/utils.d.ts +1 -1
- package/utils.js +10 -18
- package/visitors/call-expression.d.ts +1 -1
- package/visitors/call-expression.js +10 -15
- package/visitors/jsx-opening-element.d.ts +1 -1
- package/visitors/jsx-opening-element.js +11 -16
- package/lib_esnext/index.d.ts +0 -9
- package/lib_esnext/index.js +0 -69
- package/lib_esnext/types.d.ts +0 -30
- package/lib_esnext/types.js +0 -1
- package/lib_esnext/utils.d.ts +0 -33
- package/lib_esnext/utils.js +0 -143
- package/lib_esnext/visitors/call-expression.d.ts +0 -5
- package/lib_esnext/visitors/call-expression.js +0 -119
- package/lib_esnext/visitors/jsx-opening-element.d.ts +0 -5
- package/lib_esnext/visitors/jsx-opening-element.js +0 -82
package/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PluginObj, PluginPass } from '@babel/core';
|
|
2
|
-
import { ExtractedMessageDescriptor, Options } from './types';
|
|
2
|
+
import { ExtractedMessageDescriptor, Options } from './types.js';
|
|
3
3
|
export type ExtractionResult<M = Record<string, string>> = {
|
|
4
4
|
messages: ExtractedMessageDescriptor[];
|
|
5
5
|
meta: M;
|
package/index.js
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
const jsx_opening_element_1 = require("./visitors/jsx-opening-element");
|
|
9
|
-
exports.DEFAULT_ID_INTERPOLATION_PATTERN = '[sha512:contenthash:base64:6]';
|
|
1
|
+
import { declare } from '@babel/helper-plugin-utils';
|
|
2
|
+
import babelPluginSyntaxJsxNs from '@babel/plugin-syntax-jsx';
|
|
3
|
+
import { visitor as CallExpression } from './visitors/call-expression.js';
|
|
4
|
+
import { visitor as JSXOpeningElement } from './visitors/jsx-opening-element.js';
|
|
5
|
+
const babelPluginSyntaxJsx = babelPluginSyntaxJsxNs.default || babelPluginSyntaxJsxNs;
|
|
6
|
+
console.log(babelPluginSyntaxJsxNs);
|
|
7
|
+
export const DEFAULT_ID_INTERPOLATION_PATTERN = '[sha512:contenthash:base64:6]';
|
|
10
8
|
const plugin =
|
|
11
9
|
// @ts-expect-error PluginPass doesn't allow custom state but it actually does
|
|
12
|
-
|
|
10
|
+
declare((api, options) => {
|
|
13
11
|
api.assertVersion(7);
|
|
14
12
|
if (!options.idInterpolationPattern) {
|
|
15
|
-
options.idInterpolationPattern =
|
|
13
|
+
options.idInterpolationPattern = DEFAULT_ID_INTERPOLATION_PATTERN;
|
|
16
14
|
}
|
|
17
15
|
const { pragma } = options;
|
|
18
16
|
const componentNames = new Set(options.additionalComponentNames);
|
|
@@ -24,7 +22,7 @@ const plugin =
|
|
|
24
22
|
// Vue
|
|
25
23
|
functionNames.add('$formatMessage');
|
|
26
24
|
return {
|
|
27
|
-
inherits:
|
|
25
|
+
inherits: babelPluginSyntaxJsx,
|
|
28
26
|
pre() {
|
|
29
27
|
this.componentNames = Array.from(componentNames);
|
|
30
28
|
this.functionNames = Array.from(functionNames);
|
|
@@ -65,9 +63,9 @@ const plugin =
|
|
|
65
63
|
}
|
|
66
64
|
},
|
|
67
65
|
},
|
|
68
|
-
JSXOpeningElement
|
|
69
|
-
CallExpression
|
|
66
|
+
JSXOpeningElement,
|
|
67
|
+
CallExpression,
|
|
70
68
|
},
|
|
71
69
|
};
|
|
72
70
|
});
|
|
73
|
-
|
|
71
|
+
export default plugin;
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "babel-plugin-formatjs",
|
|
3
3
|
"description": "Extracts string messages for translation from modules that use formatjs.",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "11.0.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Long Ho <holevietlong@gmail.com>",
|
|
7
|
+
"type": "module",
|
|
7
8
|
"types": "index.d.ts",
|
|
8
9
|
"dependencies": {
|
|
9
10
|
"@babel/core": "^7.26.10",
|
|
@@ -15,8 +16,8 @@
|
|
|
15
16
|
"@types/babel__helper-plugin-utils": "^7.10.3",
|
|
16
17
|
"@types/babel__traverse": "^7.20.6",
|
|
17
18
|
"tslib": "^2.8.0",
|
|
18
|
-
"@formatjs/icu-messageformat-parser": "
|
|
19
|
-
"@formatjs/ts-transformer": "
|
|
19
|
+
"@formatjs/icu-messageformat-parser": "3.0.1",
|
|
20
|
+
"@formatjs/ts-transformer": "4.0.1"
|
|
20
21
|
},
|
|
21
22
|
"bugs": "https://github.com/formatjs/formatjs/issues",
|
|
22
23
|
"gitHead": "8b0baec8eda5002715cf893274fe59782fc2d371",
|
package/types.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
package/utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as t from '@babel/types';
|
|
2
2
|
import { NodePath } from '@babel/core';
|
|
3
|
-
import { ExtractedMessageDescriptor, MessageDescriptor, MessageDescriptorPath, Options } from './types';
|
|
3
|
+
import { ExtractedMessageDescriptor, MessageDescriptor, MessageDescriptorPath, Options } from './types.js';
|
|
4
4
|
export declare function getMessageDescriptorKey(path: NodePath<any>): string;
|
|
5
5
|
export declare function createMessageDescriptor(propPaths: [
|
|
6
6
|
NodePath<t.JSXIdentifier> | NodePath<t.Identifier>,
|
package/utils.js
CHANGED
|
@@ -1,13 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.getMessageDescriptorKey = getMessageDescriptorKey;
|
|
4
|
-
exports.createMessageDescriptor = createMessageDescriptor;
|
|
5
|
-
exports.evaluateMessageDescriptor = evaluateMessageDescriptor;
|
|
6
|
-
exports.tagAsExtracted = tagAsExtracted;
|
|
7
|
-
exports.wasExtracted = wasExtracted;
|
|
8
|
-
exports.storeMessage = storeMessage;
|
|
9
|
-
const icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
|
|
10
|
-
const ts_transformer_1 = require("@formatjs/ts-transformer");
|
|
1
|
+
import { parse } from '@formatjs/icu-messageformat-parser';
|
|
2
|
+
import { interpolateName } from '@formatjs/ts-transformer';
|
|
11
3
|
const DESCRIPTOR_PROPS = new Set([
|
|
12
4
|
'id',
|
|
13
5
|
'description',
|
|
@@ -20,7 +12,7 @@ function evaluatePath(path) {
|
|
|
20
12
|
}
|
|
21
13
|
throw path.buildCodeFrameError('[React Intl] Messages must be statically evaluate-able for extraction.');
|
|
22
14
|
}
|
|
23
|
-
function getMessageDescriptorKey(path) {
|
|
15
|
+
export function getMessageDescriptorKey(path) {
|
|
24
16
|
if (path.isIdentifier() || path.isJSXIdentifier()) {
|
|
25
17
|
return path.node.name;
|
|
26
18
|
}
|
|
@@ -41,7 +33,7 @@ function getMessageDescriptorValue(path, isMessageNode) {
|
|
|
41
33
|
const descriptorValue = evaluatePath(path);
|
|
42
34
|
return descriptorValue;
|
|
43
35
|
}
|
|
44
|
-
function createMessageDescriptor(propPaths) {
|
|
36
|
+
export function createMessageDescriptor(propPaths) {
|
|
45
37
|
return propPaths.reduce((hash, [keyPath, valuePath]) => {
|
|
46
38
|
const key = getMessageDescriptorKey(keyPath);
|
|
47
39
|
if (DESCRIPTOR_PROPS.has(key)) {
|
|
@@ -54,7 +46,7 @@ function createMessageDescriptor(propPaths) {
|
|
|
54
46
|
description: undefined,
|
|
55
47
|
});
|
|
56
48
|
}
|
|
57
|
-
function evaluateMessageDescriptor(descriptorPath, isJSXSource = false, filename, idInterpolationPattern, overrideIdFn, preserveWhitespace) {
|
|
49
|
+
export function evaluateMessageDescriptor(descriptorPath, isJSXSource = false, filename, idInterpolationPattern, overrideIdFn, preserveWhitespace) {
|
|
58
50
|
let id = getMessageDescriptorValue(descriptorPath.id);
|
|
59
51
|
const defaultMessage = getICUMessageValue(descriptorPath.defaultMessage, {
|
|
60
52
|
isJSXSource,
|
|
@@ -64,7 +56,7 @@ function evaluateMessageDescriptor(descriptorPath, isJSXSource = false, filename
|
|
|
64
56
|
id = overrideIdFn(id, defaultMessage, description, filename);
|
|
65
57
|
}
|
|
66
58
|
else if (!id && idInterpolationPattern && defaultMessage) {
|
|
67
|
-
id =
|
|
59
|
+
id = interpolateName({ resourcePath: filename }, idInterpolationPattern, {
|
|
68
60
|
content: description
|
|
69
61
|
? `${defaultMessage}#${description}`
|
|
70
62
|
: defaultMessage,
|
|
@@ -90,7 +82,7 @@ function getICUMessageValue(messagePath, { isJSXSource = false } = {}, preserveW
|
|
|
90
82
|
message = message.trim().replace(/\s+/gm, ' ');
|
|
91
83
|
}
|
|
92
84
|
try {
|
|
93
|
-
|
|
85
|
+
parse(message);
|
|
94
86
|
}
|
|
95
87
|
catch (parseError) {
|
|
96
88
|
if (isJSXSource &&
|
|
@@ -118,14 +110,14 @@ const EXTRACTED = Symbol('FormatJSExtracted');
|
|
|
118
110
|
* multiple plugin runs
|
|
119
111
|
* @param path
|
|
120
112
|
*/
|
|
121
|
-
function tagAsExtracted(path) {
|
|
113
|
+
export function tagAsExtracted(path) {
|
|
122
114
|
path.node[EXTRACTED] = true;
|
|
123
115
|
}
|
|
124
116
|
/**
|
|
125
117
|
* Check if a node was extracted
|
|
126
118
|
* @param path
|
|
127
119
|
*/
|
|
128
|
-
function wasExtracted(path) {
|
|
120
|
+
export function wasExtracted(path) {
|
|
129
121
|
return !!path.node[EXTRACTED];
|
|
130
122
|
}
|
|
131
123
|
/**
|
|
@@ -136,7 +128,7 @@ function wasExtracted(path) {
|
|
|
136
128
|
* @param filename
|
|
137
129
|
* @param messages
|
|
138
130
|
*/
|
|
139
|
-
function storeMessage({ id, description, defaultMessage }, path, { extractSourceLocation }, filename, messages) {
|
|
131
|
+
export function storeMessage({ id, description, defaultMessage }, path, { extractSourceLocation }, filename, messages) {
|
|
140
132
|
if (!id && !defaultMessage) {
|
|
141
133
|
throw path.buildCodeFrameError('[React Intl] Message Descriptors require an `id` or `defaultMessage`.');
|
|
142
134
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PluginPass } from '@babel/core';
|
|
2
2
|
import * as t from '@babel/types';
|
|
3
|
-
import { State } from '../types';
|
|
3
|
+
import { State } from '../types.js';
|
|
4
4
|
import { VisitNodeFunction } from '@babel/traverse';
|
|
5
5
|
export declare const visitor: VisitNodeFunction<PluginPass & State, t.CallExpression>;
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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");
|
|
1
|
+
import * as t from '@babel/types';
|
|
2
|
+
import { createMessageDescriptor, evaluateMessageDescriptor, wasExtracted, storeMessage, tagAsExtracted, } from '../utils.js';
|
|
3
|
+
import { parse } from '@formatjs/icu-messageformat-parser';
|
|
8
4
|
function assertObjectExpression(path, callee) {
|
|
9
5
|
if (!path || !path.isObjectExpression()) {
|
|
10
6
|
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.`);
|
|
@@ -29,9 +25,9 @@ function getMessagesObjectFromExpression(nodePath) {
|
|
|
29
25
|
}
|
|
30
26
|
return currentPath;
|
|
31
27
|
}
|
|
32
|
-
const visitor = function (path, { opts, file: { opts: { filename }, }, }) {
|
|
28
|
+
export const visitor = function (path, { opts, file: { opts: { filename }, }, }) {
|
|
33
29
|
const { overrideIdFn, idInterpolationPattern, removeDefaultMessage, ast, preserveWhitespace, } = opts;
|
|
34
|
-
if (
|
|
30
|
+
if (wasExtracted(path)) {
|
|
35
31
|
return;
|
|
36
32
|
}
|
|
37
33
|
const { messages, functionNames } = this;
|
|
@@ -44,14 +40,14 @@ const visitor = function (path, { opts, file: { opts: { filename }, }, }) {
|
|
|
44
40
|
function processMessageObject(messageDescriptor) {
|
|
45
41
|
assertObjectExpression(messageDescriptor, callee);
|
|
46
42
|
const properties = messageDescriptor.get('properties');
|
|
47
|
-
const descriptorPath =
|
|
43
|
+
const descriptorPath = createMessageDescriptor(properties.map(prop => [prop.get('key'), prop.get('value')]));
|
|
48
44
|
// If the message is already compiled, don't re-compile it
|
|
49
45
|
if (descriptorPath.defaultMessage?.isArrayExpression()) {
|
|
50
46
|
return;
|
|
51
47
|
}
|
|
52
48
|
// Evaluate the Message Descriptor values, then store it.
|
|
53
|
-
const descriptor =
|
|
54
|
-
|
|
49
|
+
const descriptor = evaluateMessageDescriptor(descriptorPath, false, filename || undefined, idInterpolationPattern, overrideIdFn, preserveWhitespace);
|
|
50
|
+
storeMessage(descriptor, messageDescriptor, opts, filename || undefined, messages);
|
|
55
51
|
const firstProp = properties[0];
|
|
56
52
|
const defaultMessageProp = properties.find(prop => {
|
|
57
53
|
const keyProp = prop.get('key');
|
|
@@ -86,14 +82,14 @@ const visitor = function (path, { opts, file: { opts: { filename }, }, }) {
|
|
|
86
82
|
else if (descriptor.defaultMessage) {
|
|
87
83
|
const valueProp = defaultMessageProp.get('value');
|
|
88
84
|
if (ast) {
|
|
89
|
-
valueProp.replaceWithSourceString(JSON.stringify(
|
|
85
|
+
valueProp.replaceWithSourceString(JSON.stringify(parse(descriptor.defaultMessage)));
|
|
90
86
|
}
|
|
91
87
|
else {
|
|
92
88
|
valueProp.replaceWith(t.stringLiteral(descriptor.defaultMessage));
|
|
93
89
|
}
|
|
94
90
|
}
|
|
95
91
|
}
|
|
96
|
-
|
|
92
|
+
tagAsExtracted(path);
|
|
97
93
|
}
|
|
98
94
|
// Check that this is `defineMessages` call
|
|
99
95
|
if (callee.isIdentifier({ name: 'defineMessages' }) ||
|
|
@@ -121,4 +117,3 @@ const visitor = function (path, { opts, file: { opts: { filename }, }, }) {
|
|
|
121
117
|
}
|
|
122
118
|
}
|
|
123
119
|
};
|
|
124
|
-
exports.visitor = visitor;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PluginPass } from '@babel/core';
|
|
2
|
-
import { State } from '../types';
|
|
2
|
+
import { State } from '../types.js';
|
|
3
3
|
import * as t from '@babel/types';
|
|
4
4
|
import { VisitNodeFunction } from '@babel/traverse';
|
|
5
5
|
export declare const visitor: VisitNodeFunction<PluginPass & State, t.JSXOpeningElement>;
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
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 }, }, }) {
|
|
1
|
+
import * as t from '@babel/types';
|
|
2
|
+
import { parse } from '@formatjs/icu-messageformat-parser';
|
|
3
|
+
import { createMessageDescriptor, evaluateMessageDescriptor, getMessageDescriptorKey, storeMessage, tagAsExtracted, wasExtracted, } from '../utils.js';
|
|
4
|
+
export const visitor = function (path, { opts, file: { opts: { filename }, }, }) {
|
|
9
5
|
const { removeDefaultMessage, idInterpolationPattern, overrideIdFn, ast, preserveWhitespace, } = opts;
|
|
10
6
|
const { componentNames, messages } = this;
|
|
11
|
-
if (
|
|
7
|
+
if (wasExtracted(path)) {
|
|
12
8
|
return;
|
|
13
9
|
}
|
|
14
10
|
const name = path.get('name');
|
|
@@ -18,7 +14,7 @@ const visitor = function (path, { opts, file: { opts: { filename }, }, }) {
|
|
|
18
14
|
const attributes = path
|
|
19
15
|
.get('attributes')
|
|
20
16
|
.filter(attr => attr.isJSXAttribute());
|
|
21
|
-
const descriptorPath =
|
|
17
|
+
const descriptorPath = createMessageDescriptor(attributes.map(attr => [
|
|
22
18
|
attr.get('name'),
|
|
23
19
|
attr.get('value'),
|
|
24
20
|
]));
|
|
@@ -33,8 +29,8 @@ const visitor = function (path, { opts, file: { opts: { filename }, }, }) {
|
|
|
33
29
|
}
|
|
34
30
|
// Evaluate the Message Descriptor values in a JSX
|
|
35
31
|
// context, then store it.
|
|
36
|
-
const descriptor =
|
|
37
|
-
|
|
32
|
+
const descriptor = evaluateMessageDescriptor(descriptorPath, true, filename || undefined, idInterpolationPattern, overrideIdFn, preserveWhitespace);
|
|
33
|
+
storeMessage(descriptor, path, opts, filename || undefined, messages);
|
|
38
34
|
let idAttr;
|
|
39
35
|
let descriptionAttr;
|
|
40
36
|
let defaultMessageAttr;
|
|
@@ -43,7 +39,7 @@ const visitor = function (path, { opts, file: { opts: { filename }, }, }) {
|
|
|
43
39
|
if (!attr.isJSXAttribute()) {
|
|
44
40
|
continue;
|
|
45
41
|
}
|
|
46
|
-
switch (
|
|
42
|
+
switch (getMessageDescriptorKey(attr.get('name'))) {
|
|
47
43
|
case 'description':
|
|
48
44
|
descriptionAttr = attr;
|
|
49
45
|
break;
|
|
@@ -78,10 +74,9 @@ const visitor = function (path, { opts, file: { opts: { filename }, }, }) {
|
|
|
78
74
|
const valueAttr = defaultMessageAttr.get('value');
|
|
79
75
|
valueAttr
|
|
80
76
|
.get('expression')
|
|
81
|
-
.replaceWithSourceString(JSON.stringify(
|
|
77
|
+
.replaceWithSourceString(JSON.stringify(parse(descriptor.defaultMessage)));
|
|
82
78
|
}
|
|
83
79
|
}
|
|
84
80
|
// Tag the AST node so we don't try to extract it twice.
|
|
85
|
-
|
|
81
|
+
tagAsExtracted(path);
|
|
86
82
|
};
|
|
87
|
-
exports.visitor = visitor;
|
package/lib_esnext/index.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { PluginObj, PluginPass } from '@babel/core';
|
|
2
|
-
import { ExtractedMessageDescriptor, Options } from './types';
|
|
3
|
-
export 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 plugin: (api: object, options: Options | null | undefined, dirname: string) => PluginObj<PluginPass>;
|
|
9
|
-
export default plugin;
|
package/lib_esnext/index.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { declare } from '@babel/helper-plugin-utils';
|
|
2
|
-
import babelPluginSyntaxJsx from '@babel/plugin-syntax-jsx';
|
|
3
|
-
import { visitor as CallExpression } from './visitors/call-expression';
|
|
4
|
-
import { visitor as JSXOpeningElement } from './visitors/jsx-opening-element';
|
|
5
|
-
export const DEFAULT_ID_INTERPOLATION_PATTERN = '[sha512:contenthash:base64:6]';
|
|
6
|
-
const plugin =
|
|
7
|
-
// @ts-expect-error PluginPass doesn't allow custom state but it actually does
|
|
8
|
-
declare((api, options) => {
|
|
9
|
-
api.assertVersion(7);
|
|
10
|
-
if (!options.idInterpolationPattern) {
|
|
11
|
-
options.idInterpolationPattern = DEFAULT_ID_INTERPOLATION_PATTERN;
|
|
12
|
-
}
|
|
13
|
-
const { pragma } = options;
|
|
14
|
-
const componentNames = new Set(options.additionalComponentNames);
|
|
15
|
-
componentNames.add('FormattedMessage');
|
|
16
|
-
const functionNames = new Set(options.additionalFunctionNames);
|
|
17
|
-
functionNames.add('formatMessage');
|
|
18
|
-
// Short hand
|
|
19
|
-
functionNames.add('$t');
|
|
20
|
-
// Vue
|
|
21
|
-
functionNames.add('$formatMessage');
|
|
22
|
-
return {
|
|
23
|
-
inherits: babelPluginSyntaxJsx,
|
|
24
|
-
pre() {
|
|
25
|
-
this.componentNames = Array.from(componentNames);
|
|
26
|
-
this.functionNames = Array.from(functionNames);
|
|
27
|
-
},
|
|
28
|
-
visitor: {
|
|
29
|
-
Program: {
|
|
30
|
-
enter(path) {
|
|
31
|
-
this.messages = [];
|
|
32
|
-
this.meta = {};
|
|
33
|
-
if (!pragma) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
for (const { leadingComments } of path.node.body) {
|
|
37
|
-
if (!leadingComments) {
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
const pragmaLineNode = leadingComments.find(c => c.value.includes(pragma));
|
|
41
|
-
if (!pragmaLineNode) {
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
pragmaLineNode.value
|
|
45
|
-
.split(pragma)[1]
|
|
46
|
-
.trim()
|
|
47
|
-
.split(/\s+/g)
|
|
48
|
-
.forEach(kv => {
|
|
49
|
-
const [k, v] = kv.split(':');
|
|
50
|
-
this.meta[k] = v;
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
|
-
exit(_, { opts: _opts, file: { opts: { filename }, }, }) {
|
|
55
|
-
const opts = _opts;
|
|
56
|
-
if (typeof opts?.onMetaExtracted === 'function') {
|
|
57
|
-
opts.onMetaExtracted(filename || '', this.meta);
|
|
58
|
-
}
|
|
59
|
-
if (typeof opts?.onMsgExtracted === 'function') {
|
|
60
|
-
opts.onMsgExtracted(filename || '', this.messages);
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
JSXOpeningElement,
|
|
65
|
-
CallExpression,
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
});
|
|
69
|
-
export default plugin;
|
package/lib_esnext/types.d.ts
DELETED
|
@@ -1,30 +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 type ExtractedMessageDescriptor = MessageDescriptor & Partial<SourceLocation> & {
|
|
15
|
-
file?: string;
|
|
16
|
-
};
|
|
17
|
-
export 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
|
-
}
|
package/lib_esnext/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/lib_esnext/utils.d.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import * as t from '@babel/types';
|
|
2
|
-
import { NodePath } from '@babel/core';
|
|
3
|
-
import { ExtractedMessageDescriptor, MessageDescriptor, MessageDescriptorPath, Options } from './types';
|
|
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;
|
package/lib_esnext/utils.js
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { parse } from '@formatjs/icu-messageformat-parser';
|
|
2
|
-
import { interpolateName } from '@formatjs/ts-transformer';
|
|
3
|
-
const DESCRIPTOR_PROPS = new Set([
|
|
4
|
-
'id',
|
|
5
|
-
'description',
|
|
6
|
-
'defaultMessage',
|
|
7
|
-
]);
|
|
8
|
-
function evaluatePath(path) {
|
|
9
|
-
const evaluated = path.evaluate();
|
|
10
|
-
if (evaluated.confident) {
|
|
11
|
-
return evaluated.value;
|
|
12
|
-
}
|
|
13
|
-
throw path.buildCodeFrameError('[React Intl] Messages must be statically evaluate-able for extraction.');
|
|
14
|
-
}
|
|
15
|
-
export function getMessageDescriptorKey(path) {
|
|
16
|
-
if (path.isIdentifier() || path.isJSXIdentifier()) {
|
|
17
|
-
return path.node.name;
|
|
18
|
-
}
|
|
19
|
-
return evaluatePath(path);
|
|
20
|
-
}
|
|
21
|
-
function getMessageDescriptorValue(path, isMessageNode) {
|
|
22
|
-
if (!path) {
|
|
23
|
-
return '';
|
|
24
|
-
}
|
|
25
|
-
if (path.isJSXExpressionContainer()) {
|
|
26
|
-
// If this is already compiled, no need to recompiled it
|
|
27
|
-
if (isMessageNode && path.get('expression').isArrayExpression()) {
|
|
28
|
-
return '';
|
|
29
|
-
}
|
|
30
|
-
path = path.get('expression');
|
|
31
|
-
}
|
|
32
|
-
// Always trim the Message Descriptor values.
|
|
33
|
-
const descriptorValue = evaluatePath(path);
|
|
34
|
-
return descriptorValue;
|
|
35
|
-
}
|
|
36
|
-
export function createMessageDescriptor(propPaths) {
|
|
37
|
-
return propPaths.reduce((hash, [keyPath, valuePath]) => {
|
|
38
|
-
const key = getMessageDescriptorKey(keyPath);
|
|
39
|
-
if (DESCRIPTOR_PROPS.has(key)) {
|
|
40
|
-
hash[key] = valuePath;
|
|
41
|
-
}
|
|
42
|
-
return hash;
|
|
43
|
-
}, {
|
|
44
|
-
id: undefined,
|
|
45
|
-
defaultMessage: undefined,
|
|
46
|
-
description: undefined,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
export function evaluateMessageDescriptor(descriptorPath, isJSXSource = false, filename, idInterpolationPattern, overrideIdFn, preserveWhitespace) {
|
|
50
|
-
let id = getMessageDescriptorValue(descriptorPath.id);
|
|
51
|
-
const defaultMessage = getICUMessageValue(descriptorPath.defaultMessage, {
|
|
52
|
-
isJSXSource,
|
|
53
|
-
}, preserveWhitespace);
|
|
54
|
-
const description = getMessageDescriptorValue(descriptorPath.description);
|
|
55
|
-
if (overrideIdFn) {
|
|
56
|
-
id = overrideIdFn(id, defaultMessage, description, filename);
|
|
57
|
-
}
|
|
58
|
-
else if (!id && idInterpolationPattern && defaultMessage) {
|
|
59
|
-
id = interpolateName({ resourcePath: filename }, idInterpolationPattern, {
|
|
60
|
-
content: description
|
|
61
|
-
? `${defaultMessage}#${description}`
|
|
62
|
-
: defaultMessage,
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
const descriptor = {
|
|
66
|
-
id,
|
|
67
|
-
};
|
|
68
|
-
if (description) {
|
|
69
|
-
descriptor.description = description;
|
|
70
|
-
}
|
|
71
|
-
if (defaultMessage) {
|
|
72
|
-
descriptor.defaultMessage = defaultMessage;
|
|
73
|
-
}
|
|
74
|
-
return descriptor;
|
|
75
|
-
}
|
|
76
|
-
function getICUMessageValue(messagePath, { isJSXSource = false } = {}, preserveWhitespace) {
|
|
77
|
-
if (!messagePath) {
|
|
78
|
-
return '';
|
|
79
|
-
}
|
|
80
|
-
let message = getMessageDescriptorValue(messagePath, true);
|
|
81
|
-
if (!preserveWhitespace) {
|
|
82
|
-
message = message.trim().replace(/\s+/gm, ' ');
|
|
83
|
-
}
|
|
84
|
-
try {
|
|
85
|
-
parse(message);
|
|
86
|
-
}
|
|
87
|
-
catch (parseError) {
|
|
88
|
-
if (isJSXSource &&
|
|
89
|
-
messagePath.isLiteral() &&
|
|
90
|
-
message.indexOf('\\\\') >= 0) {
|
|
91
|
-
throw messagePath.buildCodeFrameError('[React Intl] Message failed to parse. ' +
|
|
92
|
-
'It looks like `\\`s were used for escaping, ' +
|
|
93
|
-
"this won't work with JSX string literals. " +
|
|
94
|
-
'Wrap with `{}`. ' +
|
|
95
|
-
'See: http://facebook.github.io/react/docs/jsx-gotchas.html');
|
|
96
|
-
}
|
|
97
|
-
throw messagePath.buildCodeFrameError('[React Intl] Message failed to parse. ' +
|
|
98
|
-
'See: https://formatjs.github.io/docs/core-concepts/icu-syntax' +
|
|
99
|
-
`\n${parseError}`);
|
|
100
|
-
}
|
|
101
|
-
return message;
|
|
102
|
-
}
|
|
103
|
-
const EXTRACTED = Symbol('FormatJSExtracted');
|
|
104
|
-
/**
|
|
105
|
-
* Tag a node as extracted
|
|
106
|
-
* Store this in the node itself so that multiple passes work. Specifically
|
|
107
|
-
* if we remove `description` in the 1st pass, 2nd pass will fail since
|
|
108
|
-
* it expect `description` to be there.
|
|
109
|
-
* HACK: We store this in the node instance since this persists across
|
|
110
|
-
* multiple plugin runs
|
|
111
|
-
* @param path
|
|
112
|
-
*/
|
|
113
|
-
export function tagAsExtracted(path) {
|
|
114
|
-
path.node[EXTRACTED] = true;
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Check if a node was extracted
|
|
118
|
-
* @param path
|
|
119
|
-
*/
|
|
120
|
-
export function wasExtracted(path) {
|
|
121
|
-
return !!path.node[EXTRACTED];
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Store a message in our global messages
|
|
125
|
-
* @param messageDescriptor
|
|
126
|
-
* @param path
|
|
127
|
-
* @param opts
|
|
128
|
-
* @param filename
|
|
129
|
-
* @param messages
|
|
130
|
-
*/
|
|
131
|
-
export function storeMessage({ id, description, defaultMessage }, path, { extractSourceLocation }, filename, messages) {
|
|
132
|
-
if (!id && !defaultMessage) {
|
|
133
|
-
throw path.buildCodeFrameError('[React Intl] Message Descriptors require an `id` or `defaultMessage`.');
|
|
134
|
-
}
|
|
135
|
-
let loc = {};
|
|
136
|
-
if (extractSourceLocation) {
|
|
137
|
-
loc = {
|
|
138
|
-
file: filename,
|
|
139
|
-
...path.node.loc,
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
messages.push({ id, description, defaultMessage, ...loc });
|
|
143
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import * as t from '@babel/types';
|
|
2
|
-
import { createMessageDescriptor, evaluateMessageDescriptor, wasExtracted, storeMessage, tagAsExtracted, } from '../utils';
|
|
3
|
-
import { parse } from '@formatjs/icu-messageformat-parser';
|
|
4
|
-
function assertObjectExpression(path, callee) {
|
|
5
|
-
if (!path || !path.isObjectExpression()) {
|
|
6
|
-
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.`);
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
function isFormatMessageCall(callee, functionNames) {
|
|
10
|
-
if (functionNames.find(name => callee.isIdentifier({ name }))) {
|
|
11
|
-
return true;
|
|
12
|
-
}
|
|
13
|
-
if (callee.isMemberExpression()) {
|
|
14
|
-
const property = callee.get('property');
|
|
15
|
-
return !!functionNames.find(name => property.isIdentifier({ name }));
|
|
16
|
-
}
|
|
17
|
-
return false;
|
|
18
|
-
}
|
|
19
|
-
function getMessagesObjectFromExpression(nodePath) {
|
|
20
|
-
let currentPath = nodePath;
|
|
21
|
-
while (t.isTSAsExpression(currentPath.node) ||
|
|
22
|
-
t.isTSTypeAssertion(currentPath.node) ||
|
|
23
|
-
t.isTypeCastExpression(currentPath.node)) {
|
|
24
|
-
currentPath = currentPath.get('expression');
|
|
25
|
-
}
|
|
26
|
-
return currentPath;
|
|
27
|
-
}
|
|
28
|
-
export const visitor = function (path, { opts, file: { opts: { filename }, }, }) {
|
|
29
|
-
const { overrideIdFn, idInterpolationPattern, removeDefaultMessage, ast, preserveWhitespace, } = opts;
|
|
30
|
-
if (wasExtracted(path)) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
const { messages, functionNames } = this;
|
|
34
|
-
const callee = path.get('callee');
|
|
35
|
-
const args = path.get('arguments');
|
|
36
|
-
/**
|
|
37
|
-
* Process MessageDescriptor
|
|
38
|
-
* @param messageDescriptor Message Descriptor
|
|
39
|
-
*/
|
|
40
|
-
function processMessageObject(messageDescriptor) {
|
|
41
|
-
assertObjectExpression(messageDescriptor, callee);
|
|
42
|
-
const properties = messageDescriptor.get('properties');
|
|
43
|
-
const descriptorPath = createMessageDescriptor(properties.map(prop => [prop.get('key'), prop.get('value')]));
|
|
44
|
-
// If the message is already compiled, don't re-compile it
|
|
45
|
-
if (descriptorPath.defaultMessage?.isArrayExpression()) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
// Evaluate the Message Descriptor values, then store it.
|
|
49
|
-
const descriptor = evaluateMessageDescriptor(descriptorPath, false, filename || undefined, idInterpolationPattern, overrideIdFn, preserveWhitespace);
|
|
50
|
-
storeMessage(descriptor, messageDescriptor, opts, filename || undefined, messages);
|
|
51
|
-
const firstProp = properties[0];
|
|
52
|
-
const defaultMessageProp = properties.find(prop => {
|
|
53
|
-
const keyProp = prop.get('key');
|
|
54
|
-
return (keyProp.isIdentifier({ name: 'defaultMessage' }) ||
|
|
55
|
-
keyProp.isStringLiteral({ value: 'defaultMessage' }));
|
|
56
|
-
});
|
|
57
|
-
const idProp = properties.find(prop => {
|
|
58
|
-
const keyProp = prop.get('key');
|
|
59
|
-
return (keyProp.isIdentifier({ name: 'id' }) ||
|
|
60
|
-
keyProp.isStringLiteral({ value: 'id' }));
|
|
61
|
-
});
|
|
62
|
-
// Insert ID potentially 1st before removing nodes
|
|
63
|
-
if (idProp) {
|
|
64
|
-
idProp.get('value').replaceWith(t.stringLiteral(descriptor.id));
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
firstProp.insertBefore(t.objectProperty(t.identifier('id'), t.stringLiteral(descriptor.id)));
|
|
68
|
-
}
|
|
69
|
-
// Remove description
|
|
70
|
-
properties
|
|
71
|
-
.find(prop => {
|
|
72
|
-
const keyProp = prop.get('key');
|
|
73
|
-
return (keyProp.isIdentifier({ name: 'description' }) ||
|
|
74
|
-
keyProp.isStringLiteral({ value: 'description' }));
|
|
75
|
-
})
|
|
76
|
-
?.remove();
|
|
77
|
-
// Pre-parse or remove defaultMessage
|
|
78
|
-
if (defaultMessageProp) {
|
|
79
|
-
if (removeDefaultMessage) {
|
|
80
|
-
defaultMessageProp?.remove();
|
|
81
|
-
}
|
|
82
|
-
else if (descriptor.defaultMessage) {
|
|
83
|
-
const valueProp = defaultMessageProp.get('value');
|
|
84
|
-
if (ast) {
|
|
85
|
-
valueProp.replaceWithSourceString(JSON.stringify(parse(descriptor.defaultMessage)));
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
valueProp.replaceWith(t.stringLiteral(descriptor.defaultMessage));
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
tagAsExtracted(path);
|
|
93
|
-
}
|
|
94
|
-
// Check that this is `defineMessages` call
|
|
95
|
-
if (callee.isIdentifier({ name: 'defineMessages' }) ||
|
|
96
|
-
callee.isIdentifier({ name: 'defineMessage' })) {
|
|
97
|
-
const firstArgument = args[0];
|
|
98
|
-
const messagesObj = getMessagesObjectFromExpression(firstArgument);
|
|
99
|
-
assertObjectExpression(messagesObj, callee);
|
|
100
|
-
if (callee.isIdentifier({ name: 'defineMessage' })) {
|
|
101
|
-
processMessageObject(messagesObj);
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
const properties = messagesObj.get('properties');
|
|
105
|
-
if (Array.isArray(properties)) {
|
|
106
|
-
properties
|
|
107
|
-
.map(prop => prop.get('value'))
|
|
108
|
-
.forEach(processMessageObject);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
// Check that this is `intl.formatMessage` call
|
|
113
|
-
if (isFormatMessageCall(callee, functionNames)) {
|
|
114
|
-
const messageDescriptor = args[0];
|
|
115
|
-
if (messageDescriptor && messageDescriptor.isObjectExpression()) {
|
|
116
|
-
processMessageObject(messageDescriptor);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
};
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import * as t from '@babel/types';
|
|
2
|
-
import { parse } from '@formatjs/icu-messageformat-parser';
|
|
3
|
-
import { createMessageDescriptor, evaluateMessageDescriptor, getMessageDescriptorKey, storeMessage, tagAsExtracted, wasExtracted, } from '../utils';
|
|
4
|
-
export const visitor = function (path, { opts, file: { opts: { filename }, }, }) {
|
|
5
|
-
const { removeDefaultMessage, idInterpolationPattern, overrideIdFn, ast, preserveWhitespace, } = opts;
|
|
6
|
-
const { componentNames, messages } = this;
|
|
7
|
-
if (wasExtracted(path)) {
|
|
8
|
-
return;
|
|
9
|
-
}
|
|
10
|
-
const name = path.get('name');
|
|
11
|
-
if (!componentNames.find(n => name.isJSXIdentifier({ name: n }))) {
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
const attributes = path
|
|
15
|
-
.get('attributes')
|
|
16
|
-
.filter(attr => attr.isJSXAttribute());
|
|
17
|
-
const descriptorPath = createMessageDescriptor(attributes.map(attr => [
|
|
18
|
-
attr.get('name'),
|
|
19
|
-
attr.get('value'),
|
|
20
|
-
]));
|
|
21
|
-
// In order for a default message to be extracted when
|
|
22
|
-
// declaring a JSX element, it must be done with standard
|
|
23
|
-
// `key=value` attributes. But it's completely valid to
|
|
24
|
-
// write `<FormattedMessage {...descriptor} />`, because it will be
|
|
25
|
-
// skipped here and extracted elsewhere. The descriptor will
|
|
26
|
-
// be extracted only (storeMessage) if a `defaultMessage` prop.
|
|
27
|
-
if (!descriptorPath.defaultMessage) {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
// Evaluate the Message Descriptor values in a JSX
|
|
31
|
-
// context, then store it.
|
|
32
|
-
const descriptor = evaluateMessageDescriptor(descriptorPath, true, filename || undefined, idInterpolationPattern, overrideIdFn, preserveWhitespace);
|
|
33
|
-
storeMessage(descriptor, path, opts, filename || undefined, messages);
|
|
34
|
-
let idAttr;
|
|
35
|
-
let descriptionAttr;
|
|
36
|
-
let defaultMessageAttr;
|
|
37
|
-
const firstAttr = attributes[0];
|
|
38
|
-
for (const attr of attributes) {
|
|
39
|
-
if (!attr.isJSXAttribute()) {
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
switch (getMessageDescriptorKey(attr.get('name'))) {
|
|
43
|
-
case 'description':
|
|
44
|
-
descriptionAttr = attr;
|
|
45
|
-
break;
|
|
46
|
-
case 'defaultMessage':
|
|
47
|
-
defaultMessageAttr = attr;
|
|
48
|
-
break;
|
|
49
|
-
case 'id':
|
|
50
|
-
idAttr = attr;
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
// Insert ID before removing node to prevent null node insertBefore
|
|
55
|
-
if (overrideIdFn || (descriptor.id && idInterpolationPattern)) {
|
|
56
|
-
if (idAttr) {
|
|
57
|
-
idAttr.get('value').replaceWith(t.stringLiteral(descriptor.id));
|
|
58
|
-
}
|
|
59
|
-
else if (firstAttr) {
|
|
60
|
-
firstAttr.insertBefore(t.jsxAttribute(t.jsxIdentifier('id'), t.stringLiteral(descriptor.id)));
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
if (descriptionAttr) {
|
|
64
|
-
descriptionAttr.remove();
|
|
65
|
-
}
|
|
66
|
-
if (defaultMessageAttr) {
|
|
67
|
-
if (removeDefaultMessage) {
|
|
68
|
-
defaultMessageAttr.remove();
|
|
69
|
-
}
|
|
70
|
-
else if (ast && descriptor.defaultMessage) {
|
|
71
|
-
defaultMessageAttr
|
|
72
|
-
.get('value')
|
|
73
|
-
.replaceWith(t.jsxExpressionContainer(t.nullLiteral()));
|
|
74
|
-
const valueAttr = defaultMessageAttr.get('value');
|
|
75
|
-
valueAttr
|
|
76
|
-
.get('expression')
|
|
77
|
-
.replaceWithSourceString(JSON.stringify(parse(descriptor.defaultMessage)));
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
// Tag the AST node so we don't try to extract it twice.
|
|
81
|
-
tagAsExtracted(path);
|
|
82
|
-
};
|