1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | const types = require('babel-types');
|
9 |
|
10 | import {assertInput} from './errors';
|
11 | import generate from './generation';
|
12 | import {options} from './options';
|
13 |
|
14 |
|
15 |
|
16 | export function isFunctionMarker(callExpression) {
|
17 | return callExpression.callee.name === options.functionMarker;
|
18 | }
|
19 |
|
20 |
|
21 |
|
22 |
|
23 | export function nodeName(node) {
|
24 | return node.name && generate(node.name);
|
25 | }
|
26 |
|
27 | export function elementName(jsxElement) {
|
28 | return nodeName(jsxElement.openingElement);
|
29 | }
|
30 |
|
31 | export function attributeName(jsxAttribute) {
|
32 | return nodeName(jsxAttribute);
|
33 | }
|
34 |
|
35 | export function elementNamespaceOrName(jsxElement) {
|
36 | if (hasNamespacedName(jsxElement)) {
|
37 | return jsxElement.openingElement.name.namespace.name;
|
38 | } else {
|
39 | return elementName(jsxElement);
|
40 | }
|
41 | }
|
42 |
|
43 | export function elementAttributes(jsxElement) {
|
44 | return jsxElement.openingElement.attributes;
|
45 | }
|
46 |
|
47 | export function isElementMarker(jsxElement) {
|
48 | return (
|
49 | isElement(jsxElement) &&
|
50 | elementName(jsxElement) === options.elementMarker
|
51 | );
|
52 | }
|
53 |
|
54 | export function isElement(node) {
|
55 | return node.type === 'JSXElement';
|
56 | }
|
57 |
|
58 | export function isTag(jsxElement) {
|
59 | return /^[a-z]|\-/.test(elementName(jsxElement));
|
60 | }
|
61 |
|
62 | export function isComponent(jsxElement) {
|
63 | return !isTag(jsxElement);
|
64 | }
|
65 |
|
66 | export function isSimpleExpression(expression) {
|
67 | if (expression.type === 'Identifier') {
|
68 | return true;
|
69 | } else if (expression.type === 'ThisExpression') {
|
70 | return true;
|
71 | } else if (expression.type === 'MemberExpression') {
|
72 | return !expression.computed && isSimpleExpression(expression.object);
|
73 | } else {
|
74 | return false;
|
75 | }
|
76 | }
|
77 |
|
78 | export function hasNamespacedName(jsxElement) {
|
79 | return jsxElement.openingElement.name.type === 'JSXNamespacedName';
|
80 | }
|
81 |
|
82 | export function hasI18nId(jsxElement) {
|
83 | return (
|
84 | hasNamespacedName(jsxElement) ||
|
85 | hasI18nIdAttribute(jsxElement)
|
86 | );
|
87 | }
|
88 |
|
89 | export function hasI18nIdAttribute(jsxElement) {
|
90 | return elementAttributes(jsxElement).map(attributeName).indexOf('i18n-id') !== -1;
|
91 | }
|
92 |
|
93 | export function filterAttributes(jsxElement, condition) {
|
94 | jsxElement.openingElement.attributes = jsxElement.openingElement.attributes.filter(
|
95 | a => condition(jsxElement, a)
|
96 | );
|
97 | }
|
98 |
|
99 | export function i18nId(jsxElement) {
|
100 | if (hasNamespacedName(jsxElement)) {
|
101 |
|
102 | return jsxElement.openingElement.name.name.name;
|
103 | } else {
|
104 | const attr = elementAttributes(jsxElement)
|
105 | .find(a => attributeName(a) === 'i18n-id');
|
106 | if (attr) {
|
107 | assertInput(attr.value.type === 'StringLiteral',
|
108 | "i18n-id attribute found with non-StringLiteral value",
|
109 | jsxElement
|
110 | );
|
111 | return attr.value.value;
|
112 | }
|
113 | }
|
114 | }
|
115 |
|
116 | export function removeIdAttribute(jsxElement) {
|
117 | filterAttributes(jsxElement, (_, a) => attributeName(a) !== 'i18n-id');
|
118 | }
|
119 |
|
120 | export function stripI18nId(jsxElement) {
|
121 | if (jsxElement.openingElement.name.type === 'JSXNamespacedName') {
|
122 | const newName = jsxElement.openingElement.name.namespace.name;
|
123 | jsxElement.openingElement.name.type = 'JSXIdentifier';
|
124 | jsxElement.openingElement.name.name = newName;
|
125 | delete jsxElement.openingElement.name.object;
|
126 |
|
127 | if (jsxElement.closingElement) {
|
128 | jsxElement.closingElement.name.type = 'JSXIdentifier';
|
129 | jsxElement.closingElement.name.name = newName;
|
130 | delete jsxElement.closingElement.name.object;
|
131 | }
|
132 | } else {
|
133 | removeIdAttribute(jsxElement);
|
134 | }
|
135 | }
|
136 |
|
137 | export function convertToNamespacedName(jsxElement) {
|
138 | if (!hasNamespacedName(jsxElement)) {
|
139 | const name = elementName(jsxElement);
|
140 | const id = i18nId(jsxElement);
|
141 | if (id) {
|
142 | removeIdAttribute(jsxElement);
|
143 | const nameAst = types.JSXNamespacedName(
|
144 | types.JSXIdentifier(name),
|
145 | types.JSXIdentifier(id)
|
146 | );
|
147 | jsxElement.openingElement.name = nameAst;
|
148 | if (jsxElement.closingElement) {
|
149 | jsxElement.closingElement.name = nameAst;
|
150 | }
|
151 | }
|
152 | }
|
153 |
|
154 | return elementName(jsxElement);
|
155 | }
|
156 |
|
157 | export function convertNamespacedNameToIdAttribute(jsxElement) {
|
158 | if (jsxElement.openingElement.name.type === 'JSXNamespacedName') {
|
159 | const i18nId = jsxElement.openingElement.name.name.name;
|
160 | stripI18nId(jsxElement);
|
161 |
|
162 | jsxElement.openingElement.attributes.push(
|
163 | types.JSXAttribute(
|
164 | types.JSXIdentifier('i18n-id'),
|
165 | types.StringLiteral(i18nId)
|
166 | )
|
167 | );
|
168 | }
|
169 | }
|
170 |
|
171 | export function idOrComponentName(jsxElement) {
|
172 | let id = i18nId(jsxElement);
|
173 | if (!id && isComponent(jsxElement)) {
|
174 | id = elementName(jsxElement);
|
175 | }
|
176 | return id;
|
177 | };
|