@saykit/transform-jsx 0.7.0 → 0.9.0
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/dist/parser.mjs +37 -60
- package/package.json +3 -3
package/dist/parser.mjs
CHANGED
|
@@ -2,11 +2,6 @@ import { AUTO_INCREMENT_IDENTIFIER, ArgumentMessage, ChoiceMessage, CompositeMes
|
|
|
2
2
|
import { unwrapPlaceholder } from "@saykit/transform-js/parser";
|
|
3
3
|
import * as t from "@babel/types";
|
|
4
4
|
//#region src/parser.ts
|
|
5
|
-
/**
|
|
6
|
-
* Attribute used to name the ICU tag an embedded element extracts as, e.g.
|
|
7
|
-
* `<a say-tag="link">` becomes `<link></link>` rather than `<0></0>`. It never
|
|
8
|
-
* reaches the real element.
|
|
9
|
-
*/
|
|
10
5
|
const TAG_ATTRIBUTE = "say-tag";
|
|
11
6
|
const TAG_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
12
7
|
function parseJSXContainerElement(element) {
|
|
@@ -14,21 +9,7 @@ function parseJSXContainerElement(element) {
|
|
|
14
9
|
const processed = processJSXOpeningElement(element.openingElement);
|
|
15
10
|
if (!processed) return null;
|
|
16
11
|
const [accessor] = processed;
|
|
17
|
-
const children = element
|
|
18
|
-
if (t.isJSXText(c)) {
|
|
19
|
-
const text = normalizeJSXText(c.value, i === 0, i === a.length - 1);
|
|
20
|
-
if (text) p.push(new LiteralMessage(text));
|
|
21
|
-
}
|
|
22
|
-
if (t.isJSXElement(c)) p.push(parseJSXElement(c, true));
|
|
23
|
-
else if (t.isJSXFragment(c)) p.push(new ElementMessage(AUTO_INCREMENT_IDENTIFIER, [], c));
|
|
24
|
-
else if (t.isJSXExpressionContainer(c)) {
|
|
25
|
-
if (t.isExpression(c.expression)) {
|
|
26
|
-
const [identifier, value] = unwrapPlaceholder(c.expression);
|
|
27
|
-
p.push(new ArgumentMessage(identifier, value));
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return p;
|
|
31
|
-
}, []);
|
|
12
|
+
const children = buildMessageChildren(element);
|
|
32
13
|
const descriptorId = findAttributeValueIfStringLiteralAsString(element.openingElement.attributes, "id");
|
|
33
14
|
const descriptorContext = findAttributeValueIfStringLiteralAsString(element.openingElement.attributes, "context");
|
|
34
15
|
const whitespace = findAttributeValueAsBoolean(element.openingElement.attributes, "whitespace");
|
|
@@ -69,11 +50,13 @@ function parseJSXOpeningElement(element) {
|
|
|
69
50
|
identifier,
|
|
70
51
|
value: parseJSXElement(a.value.expression, true)
|
|
71
52
|
});
|
|
72
|
-
else if (t.isJSXFragment(a.value.expression))
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
53
|
+
else if (t.isJSXFragment(a.value.expression)) {
|
|
54
|
+
const fragment = a.value.expression;
|
|
55
|
+
b.push({
|
|
56
|
+
identifier,
|
|
57
|
+
value: new CompositeMessage({}, [], [], buildMessageChildren(fragment), fragment)
|
|
58
|
+
});
|
|
59
|
+
} else if (t.isExpression(a.value.expression)) {
|
|
77
60
|
const [name, value] = unwrapPlaceholder(a.value.expression);
|
|
78
61
|
b.push({
|
|
79
62
|
identifier,
|
|
@@ -102,11 +85,6 @@ function parseJSXOpeningElement(element) {
|
|
|
102
85
|
}
|
|
103
86
|
return null;
|
|
104
87
|
}
|
|
105
|
-
/**
|
|
106
|
-
* The `offset` a plural subtracts from its selector before `#` is formatted.
|
|
107
|
-
* See the JS parser's counterpart — the constraints are the same, only the
|
|
108
|
-
* syntax carrying it differs.
|
|
109
|
-
*/
|
|
110
88
|
function findPluralOffset(attributes) {
|
|
111
89
|
for (const attribute of attributes) {
|
|
112
90
|
if (!t.isJSXAttribute(attribute)) continue;
|
|
@@ -118,30 +96,35 @@ function findPluralOffset(attributes) {
|
|
|
118
96
|
return expression.value;
|
|
119
97
|
}
|
|
120
98
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
if (
|
|
144
|
-
return
|
|
99
|
+
function buildMessageChildren(element, into = []) {
|
|
100
|
+
return t.react.buildChildren(element).reduce((p, c) => {
|
|
101
|
+
const literal = getExpressionAsLiteralText(c);
|
|
102
|
+
if (literal !== void 0) pushLiteral(p, literal);
|
|
103
|
+
else if (t.isJSXElement(c)) p.push(parseJSXElement(c, true));
|
|
104
|
+
else if (t.isJSXFragment(c)) buildMessageChildren(c, p);
|
|
105
|
+
else if (t.isExpression(c)) {
|
|
106
|
+
const [identifier, value] = unwrapPlaceholder(c);
|
|
107
|
+
p.push(new ArgumentMessage(identifier, value));
|
|
108
|
+
}
|
|
109
|
+
return p;
|
|
110
|
+
}, into);
|
|
111
|
+
}
|
|
112
|
+
function pushLiteral(messages, text) {
|
|
113
|
+
if (!text) return;
|
|
114
|
+
const last = messages.at(-1);
|
|
115
|
+
if (last instanceof LiteralMessage) messages[messages.length - 1] = new LiteralMessage(last.text + text);
|
|
116
|
+
else messages.push(new LiteralMessage(text));
|
|
117
|
+
}
|
|
118
|
+
function getExpressionAsLiteralText(expression) {
|
|
119
|
+
if (t.isStringLiteral(expression)) return expression.value;
|
|
120
|
+
if (t.isNumericLiteral(expression)) return String(expression.value);
|
|
121
|
+
if (t.isUnaryExpression(expression) && (expression.operator === "-" || expression.operator === "+") && t.isNumericLiteral(expression.argument)) return String(expression.operator === "-" ? -expression.argument.value : expression.argument.value);
|
|
122
|
+
if (t.isBooleanLiteral(expression) || t.isNullLiteral(expression)) return "";
|
|
123
|
+
if (t.isTemplateLiteral(expression) && expression.expressions.length === 0) {
|
|
124
|
+
const [chunk] = expression.quasis;
|
|
125
|
+
/* v8 ignore next */
|
|
126
|
+
return chunk?.value.cooked ?? "";
|
|
127
|
+
}
|
|
145
128
|
}
|
|
146
129
|
function processJSXOpeningElement(element) {
|
|
147
130
|
if (t.isJSXIdentifier(element.name) && element.name.name === "Say") return [element.name, null];
|
|
@@ -156,12 +139,6 @@ function parseJSXElement(element, fallback) {
|
|
|
156
139
|
if (element.openingElement.selfClosing) return new ElementMessage(identifier, [], element);
|
|
157
140
|
return new ElementMessage(identifier, [parseJSXElement(t.jsxElement(t.jsxOpeningElement(t.jsxIdentifier("Say"), []), t.jsxClosingElement(t.jsxIdentifier("Say")), element.children), true)], element);
|
|
158
141
|
}
|
|
159
|
-
/**
|
|
160
|
-
* Read the tag name off an embedded element and remove the attribute so it
|
|
161
|
-
* never reaches the rendered element. Only static strings name a tag; anything
|
|
162
|
-
* else is left in place and the element falls back to an auto-incremented
|
|
163
|
-
* identifier.
|
|
164
|
-
*/
|
|
165
142
|
function takeElementTag(element) {
|
|
166
143
|
const attributes = element.openingElement.attributes;
|
|
167
144
|
const index = attributes.findIndex((a) => t.isJSXAttribute(a) && getAttributeNameAsString(a) === TAG_ATTRIBUTE);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saykit/transform-jsx",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "JSX and TSX source transformer for SayKit",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"i18n",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"@babel/parser": "^7.29.7",
|
|
48
48
|
"@babel/traverse": "^7.29.7",
|
|
49
49
|
"@babel/types": "^7.29.7",
|
|
50
|
-
"@saykit/config": "^0.
|
|
51
|
-
"@saykit/transform-js": "^0.
|
|
50
|
+
"@saykit/config": "^0.9.0",
|
|
51
|
+
"@saykit/transform-js": "^0.9.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@babel/core": "^7.29.7",
|