Socket
Socket
Sign inDemoInstall

@lingui/babel-plugin-transform-js

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@lingui/babel-plugin-transform-js - npm Package Compare versions

Comparing version 2.0.0-2 to 2.0.0-3

339

index.js

@@ -12,6 +12,2 @@ "use strict";

var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _assign = _interopRequireDefault(require("@babel/runtime/core-js/object/assign"));
var _getIterator2 = _interopRequireDefault(require("@babel/runtime/core-js/get-iterator"));

@@ -23,2 +19,4 @@

var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var nlRe = /(?:\r\n|\r|\n)+\s+/g;

@@ -32,2 +30,10 @@ var pluralRules = ["zero", "one", "two", "few", "many", "other"];

};
};
var initialProps = function initialProps() {
return {
text: "",
values: {},
formats: {}
};
}; // Plugin function

@@ -45,2 +51,6 @@

name: "t"
}) || t.isCallExpression(node.tag) && t.isMemberExpression(node.tag.callee) && t.isIdentifier(node.tag.callee.object, {
name: "i18n"
}) && t.isIdentifier(node.tag.callee.property, {
name: "t"
});

@@ -70,153 +80,207 @@ };

};
/**
* Convert identifiers to *named* arguments and everything else
* to *positional* arguments.
*
* Example:
* `world` is named argument and `new Date()` is positional one
*
* Input: `Hello ${world}, today is ${new Date()}`
* Output: `Hello {world}, today is {0}`
*/
function processMethod(node, file, props) {
function expressionToArgument(exp) {
var name = t.isIdentifier(exp) ? exp.name : argumentGenerator();
var key = t.isIdentifier(exp) ? exp : t.numericLiteral(name);
return {
name: name,
key: key
};
}
function processI18nMethod(node, file, props) {
if (t.isCallExpression(node.tag)) {
// Message with custom ID, where message is used as defaults
// i18n.t('id')`Hello World`
var defaults = node.tag.arguments[0];
if (!t.isStringLiteral(defaults)) {
throw file.buildCodeFrameError(node.tag, "Message ID must be a string");
}
var newProps = processTemplateLiteral(node.quasi, file, props);
return (0, _extends2.default)({}, newProps, {
text: defaults.value,
defaults: props.text
});
} // Message is used as the ID
// i18n.t`Hello World`
return processTemplateLiteral(node.quasi, file, props);
}
function processChoiceMethod(node, file, props) {
var root = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
var choices = {};
var choicesType = node.callee.property.name.toLowerCase();
var defaults;
var variable;
var offset = "";
var choiceArguments = node.arguments[0];
// i18n.t
if (isI18nMethod(node)) {
processTemplateLiteral(node.quasi, file, props); // i18n.plural and i18n.select
} else if (isChoiceMethod(node.callee)) {
var exp = node;
var choices = {};
var choicesType = node.callee.property.name.toLowerCase();
var variable;
var offset = "";
var arg = exp.arguments[0];
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
if (t.isStringLiteral(choiceArguments)) {
defaults = choiceArguments.value;
choiceArguments = node.arguments[1];
}
try {
for (var _iterator = (0, _getIterator2.default)(arg.properties), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var _attr = _step.value;
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
if (_attr.computed) {
throw file.buildCodeFrameError(_attr, "Computed properties aren't allowed.");
}
try {
for (var _iterator = (0, _getIterator2.default)(choiceArguments.properties), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var _attr = _step.value;
var key = _attr.key; // key is either:
// NumericLiteral => convert to `={number}`
// StringLiteral => key.value
// Literal => key.name
if (_attr.computed) {
throw file.buildCodeFrameError(_attr, "Computed properties aren't allowed.");
}
var name = t.isNumericLiteral(key) ? "=".concat(key.value) : key.name || key.value;
var key = _attr.key; // key is either:
// NumericLiteral => convert to `={number}`
// StringLiteral => key.value
// Literal => key.name
if (name === "value") {
var _exp = _attr.value;
variable = t.isIdentifier(_exp) ? _exp.name : argumentGenerator();
var name = t.isNumericLiteral(key) ? "=".concat(key.value) : key.name || key.value;
var _key = t.isIdentifier(_exp) ? _exp : t.numericLiteral(variable);
if (name === "value") {
var exp = _attr.value;
props.values[variable] = t.objectProperty(_key, _exp);
} else if (choicesType !== "select" && name === "offset") {
// offset is static parameter, so it must be either string or number
if (!t.isNumericLiteral(_attr.value) && !t.isStringLiteral(_attr.value)) {
throw file.buildCodeFrameError(node.callee, "Offset argument cannot be a variable.");
}
var _expressionToArgument = expressionToArgument(exp),
_name = _expressionToArgument.name,
_key = _expressionToArgument.key;
offset = " offset:".concat(_attr.value.value);
} else {
var value = "";
variable = _name;
props.values[_name] = t.objectProperty(_key, exp);
} else if (choicesType !== "select" && name === "offset") {
// offset is static parameter, so it must be either string or number
if (!t.isNumericLiteral(_attr.value) && !t.isStringLiteral(_attr.value)) {
throw file.buildCodeFrameError(node.callee, "Offset argument cannot be a variable.");
}
if (t.isTemplateLiteral(_attr.value)) {
props = processTemplateLiteral(_attr.value, file, (0, _assign.default)({}, props, {
text: ""
}));
value = props.text;
} else if (t.isCallExpression(_attr.value)) {
props = processMethod(_attr.value, file, (0, _assign.default)({}, props, {
text: ""
}));
value = props.text;
} else {
value = _attr.value.value;
}
offset = " offset:".concat(_attr.value.value);
} else {
var value = "";
choices[name] = value;
if (t.isTemplateLiteral(_attr.value)) {
props = processTemplateLiteral(_attr.value, file, (0, _extends2.default)({}, props, {
text: ""
}));
value = props.text;
} else if (t.isCallExpression(_attr.value)) {
props = processMethod(_attr.value, file, (0, _extends2.default)({}, props, {
text: ""
}));
value = props.text;
} else {
value = _attr.value.value;
}
} // missing value
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
choices[name] = value;
}
} // missing value
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
_iterator.return();
}
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
if (_didIteratorError) {
throw _iteratorError;
}
}
}
if (variable === undefined) {
throw file.buildCodeFrameError(node.callee, "Value argument is missing.");
}
if (variable === undefined) {
throw file.buildCodeFrameError(node.callee, "Value argument is missing.");
}
var choicesKeys = (0, _keys.default)(choices); // 'other' choice is required
var choicesKeys = (0, _keys.default)(choices); // 'other' choice is required
if (!choicesKeys.length) {
throw file.buildCodeFrameError(node.callee, "Missing ".concat(choicesType, " choices. At least fallback argument 'other' is required."));
} else if (!(0, _includes.default)(choicesKeys, "other")) {
throw file.buildCodeFrameError(node.callee, "Missing fallback argument 'other'.");
} // validate plural rules
if (!choicesKeys.length) {
throw file.buildCodeFrameError(node.callee, "Missing ".concat(choicesType, " choices. At least fallback argument 'other' is required."));
} else if (!(0, _includes.default)(choicesKeys, "other")) {
throw file.buildCodeFrameError(node.callee, "Missing fallback argument 'other'.");
} // validate plural rules
if (choicesType === "plural" || choicesType === "selectordinal") {
choicesKeys.forEach(function (rule) {
if (!(0, _includes.default)(pluralRules, rule) && !/=\d+/.test(rule)) {
throw file.buildCodeFrameError(node.callee, "Invalid plural rule '".concat(rule, "'. Must be ").concat(pluralRules.join(", "), " or exact number depending on your source language ('one' and 'other' for English)."));
}
});
}
if (choicesType === "plural" || choicesType === "selectordinal") {
choicesKeys.forEach(function (rule) {
if (!(0, _includes.default)(pluralRules, rule) && !/=\d+/.test(rule)) {
throw file.buildCodeFrameError(node.callee, "Invalid plural rule '".concat(rule, "'. Must be ").concat(pluralRules.join(", "), " or exact number depending on your source language ('one' and 'other' for English)."));
}
});
}
var argument = choicesKeys.map(function (form) {
return "".concat(form, " {").concat(choices[form], "}");
}).join(" ");
var format = "".concat(variable, ", ").concat(choicesType, ",").concat(offset, " ").concat(argument);
props.text = root ? "{".concat(format, "}") : format;
} else if (isFormatMethod(node.callee)) {
var _exp2 = node.arguments[0]; // missing value
var argument = choicesKeys.map(function (form) {
return "".concat(form, " {").concat(choices[form], "}");
}).join(" ");
var format = "".concat(variable, ", ").concat(choicesType, ",").concat(offset, " ").concat(argument);
props.text = root ? "{".concat(format, "}") : format;
if (_exp2 === undefined) {
throw file.buildCodeFrameError(node.callee, "The first argument of format function must be a variable.");
}
if (defaults) {
return (0, _extends2.default)({}, props, {
text: defaults,
defaults: props.text
});
}
var _variable = t.isIdentifier(_exp2) ? _exp2.name : argumentGenerator();
return props;
}
var _key2 = t.isIdentifier(_exp2) ? _exp2 : t.numericLiteral(_variable);
function processFormatMethod(node, file, props, root) {
var exp = node.arguments[0]; // missing value
var type = node.callee.property.name;
var parts = [_variable, // variable name
type // format type
];
var _format = "";
var formatArg = node.arguments[1];
if (exp === undefined) {
throw file.buildCodeFrameError(node.callee, "The first argument of format function must be a variable.");
}
if (!formatArg) {// Do not throw validation error when format doesn't exist
} else if (t.isStringLiteral(formatArg)) {
_format = formatArg.value;
} else if (t.isIdentifier(formatArg) || t.isObjectExpression(formatArg)) {
if (t.isIdentifier(formatArg)) {
_format = formatArg.name;
} else {
var formatName = new RegExp("^".concat(type, "\\d+$"));
var existing = (0, _keys.default)(props.formats).filter(function (name) {
return formatName.test(name);
});
_format = "".concat(type).concat(existing.length || 0);
}
var _expressionToArgument2 = expressionToArgument(exp),
name = _expressionToArgument2.name,
key = _expressionToArgument2.key;
props.formats[_format] = t.objectProperty(t.identifier(_format), formatArg);
var type = node.callee.property.name;
var parts = [name, // variable name
type // format type
];
var format = "";
var formatArg = node.arguments[1];
if (!formatArg) {// Do not throw validation error when format doesn't exist
} else if (t.isStringLiteral(formatArg)) {
format = formatArg.value;
} else if (t.isIdentifier(formatArg) || t.isObjectExpression(formatArg)) {
if (t.isIdentifier(formatArg)) {
format = formatArg.name;
} else {
throw file.buildCodeFrameError(formatArg, "Format can be either string for buil-in formats, variable or object for custom defined formats.");
var formatName = new RegExp("^".concat(type, "\\d+$"));
var existing = (0, _keys.default)(props.formats).filter(function (name) {
return formatName.test(name);
});
format = "".concat(type).concat(existing.length || 0);
}
if (_format) parts.push(_format);
props.values[_variable] = t.objectProperty(_key2, _exp2);
props.text += "".concat(parts.join(","));
props.formats[format] = t.objectProperty(t.identifier(format), formatArg);
} else {
throw file.buildCodeFrameError(formatArg, "Format can be either string for buil-in formats, variable or object for custom defined formats.");
}
if (format) parts.push(format);
props.values[name] = t.objectProperty(key, exp);
props.text += "".concat(parts.join(","));
return props;

@@ -242,4 +306,6 @@ }

} else {
var name = t.isIdentifier(item) ? item.name : argumentGenerator();
var key = t.isIdentifier(item) ? item : t.numericLiteral(name);
var _expressionToArgument3 = expressionToArgument(item),
name = _expressionToArgument3.name,
key = _expressionToArgument3.key;
props.text += "{".concat(name, "}");

@@ -252,2 +318,19 @@ props.values[name] = t.objectProperty(key, item);

function processMethod(node, file, props) {
var root = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
if (isI18nMethod(node)) {
// i18n.t
return processI18nMethod(node, file, props);
} else if (isChoiceMethod(node.callee)) {
// i18n.plural, i18n.select and i18n.selectOrdinal
return processChoiceMethod(node, file, props, root);
} else if (isFormatMethod(node.callee)) {
// i18n.date, i18n.number
return processFormatMethod(node, file, props, root);
}
return props;
}
function CallExpression(path, _ref2) {

@@ -257,9 +340,3 @@ var file = _ref2.file;

var props = processMethod(path.node, file, {
text: "",
values: {},
formats: {}
},
/* root= */
true);
var props = processMethod(path.node, file, initialProps(), true);
var text = props.text.replace(nlRe, " ").trim();

@@ -273,2 +350,6 @@ if (!text) return; // 2. Replace complex expression with single call to i18n._

tOptions.push(t.objectProperty(t.identifier("formats"), t.objectExpression(formatsList)));
}
if (props.defaults) {
tOptions.push(t.objectProperty(t.identifier("defaults"), t.stringLiteral(props.defaults)));
} // arguments of i18n._(messageId: string, values: Object, options: Object)

@@ -275,0 +356,0 @@

{
"name": "@lingui/babel-plugin-transform-js",
"version": "2.0.0-2",
"version": "2.0.0-3",
"description": "Transform lingui-i18n methods to ICU message format",

@@ -5,0 +5,0 @@ "main": "index.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc