i18next-parser
Advanced tools
Comparing version 1.0.0-beta13 to 1.0.0-beta14
# Changelog | ||
## 1.0.0-beta13 - latest | ||
## 1.0.0-beta14 - latest | ||
@@ -5,0 +5,0 @@ - The changelog for the beta can be found in the [releases](https://github.com/i18next/i18next-parser/releases) |
@@ -71,3 +71,4 @@ 'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _extends = Object.assign || function (target) {for (var i = 1; i < arguments.length; i++) {var source = arguments[i];for (var key in source) {if (Object.prototype.hasOwnProperty.call(source, key)) {target[key] = source[key];}}}return target;};var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}();var _helpers = require('./helpers'); | ||
if (parts.length > 1) { | ||
// make sure we're not pulling a 'namespace' out of a default value | ||
if (parts.length > 1 && key !== entry.defaultValue) { | ||
entry.namespace = parts.shift(); | ||
@@ -74,0 +75,0 @@ } else |
@@ -1,2 +0,2 @@ | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _extends = Object.assign || function (target) {for (var i = 1; i < arguments.length; i++) {var source = arguments[i];for (var key in source) {if (Object.prototype.hasOwnProperty.call(source, key)) {target[key] = source[key];}}}return target;};var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}();var _events = require('events');var _events2 = _interopRequireDefault(_events);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}}function _possibleConstructorReturn(self, call) {if (!self) {throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call && (typeof call === "object" || typeof call === "function") ? call : self;}function _inherits(subClass, superClass) {if (typeof superClass !== "function" && superClass !== null) {throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);}subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;}var | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}();var _events = require('events');var _events2 = _interopRequireDefault(_events);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}}function _possibleConstructorReturn(self, call) {if (!self) {throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call && (typeof call === "object" || typeof call === "function") ? call : self;}function _inherits(subClass, superClass) {if (typeof superClass !== "function" && superClass !== null) {throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);}subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;}var | ||
@@ -8,25 +8,4 @@ BaseLexer = function (_EventEmitter) {_inherits(BaseLexer, _EventEmitter); | ||
_this.functions = options.functions || ['t'];return _this; | ||
}_createClass(BaseLexer, [{ key: 'populateKeysFromArguments', value: function populateKeysFromArguments( | ||
}_createClass(BaseLexer, [{ key: 'validateString', value: function validateString( | ||
args) { | ||
var firstArgument = args.arguments[0]; | ||
var secondArgument = args.arguments[1]; | ||
var isKeyString = this.validateString(firstArgument); | ||
var isDefaultValueString = this.validateString(secondArgument); | ||
if (!isKeyString) { | ||
this.emit('warning', 'Key is not a string litteral: ' + firstArgument); | ||
} else | ||
{ | ||
var result = _extends({}, | ||
args.options, { | ||
key: firstArgument.slice(1, -1) }); | ||
if (isDefaultValueString) { | ||
result.defaultValue = secondArgument.slice(1, -1); | ||
} | ||
this.keys.push(result); | ||
} | ||
} }, { key: 'validateString', value: function validateString( | ||
string) { | ||
@@ -33,0 +12,0 @@ var regex = new RegExp('^' + BaseLexer.stringPattern + '$', 'i'); |
@@ -1,2 +0,2 @@ | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}();var _baseLexer = require('./base-lexer');var _baseLexer2 = _interopRequireDefault(_baseLexer);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}}function _possibleConstructorReturn(self, call) {if (!self) {throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call && (typeof call === "object" || typeof call === "function") ? call : self;}function _inherits(subClass, superClass) {if (typeof superClass !== "function" && superClass !== null) {throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);}subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;}var | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _extends = Object.assign || function (target) {for (var i = 1; i < arguments.length; i++) {var source = arguments[i];for (var key in source) {if (Object.prototype.hasOwnProperty.call(source, key)) {target[key] = source[key];}}}return target;};var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}();var _baseLexer = require('./base-lexer');var _baseLexer2 = _interopRequireDefault(_baseLexer);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}}function _possibleConstructorReturn(self, call) {if (!self) {throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call && (typeof call === "object" || typeof call === "function") ? call : self;}function _inherits(subClass, superClass) {if (typeof superClass !== "function" && superClass !== null) {throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);}subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;}var | ||
@@ -39,2 +39,23 @@ HandlebarsLexer = function (_BaseLexer) {_inherits(HandlebarsLexer, _BaseLexer); | ||
return result; | ||
} }, { key: 'populateKeysFromArguments', value: function populateKeysFromArguments( | ||
args) { | ||
var firstArgument = args.arguments[0]; | ||
var secondArgument = args.arguments[1]; | ||
var isKeyString = this.validateString(firstArgument); | ||
var isDefaultValueString = this.validateString(secondArgument); | ||
if (!isKeyString) { | ||
this.emit('warning', 'Key is not a string literal: ' + firstArgument); | ||
} else | ||
{ | ||
var result = _extends({}, | ||
args.options, { | ||
key: firstArgument.slice(1, -1) }); | ||
if (isDefaultValueString) { | ||
result.defaultValue = secondArgument.slice(1, -1); | ||
} | ||
this.keys.push(result); | ||
} | ||
} }, { key: 'createFunctionRegex', value: function createFunctionRegex() | ||
@@ -41,0 +62,0 @@ |
@@ -1,2 +0,3 @@ | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _extends = Object.assign || function (target) {for (var i = 1; i < arguments.length; i++) {var source = arguments[i];for (var key in source) {if (Object.prototype.hasOwnProperty.call(source, key)) {target[key] = source[key];}}}return target;};var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}();var _baseLexer = require('./base-lexer');var _baseLexer2 = _interopRequireDefault(_baseLexer);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}}function _possibleConstructorReturn(self, call) {if (!self) {throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call && (typeof call === "object" || typeof call === "function") ? call : self;}function _inherits(subClass, superClass) {if (typeof superClass !== "function" && superClass !== null) {throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);}subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;}var | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _extends = Object.assign || function (target) {for (var i = 1; i < arguments.length; i++) {var source = arguments[i];for (var key in source) {if (Object.prototype.hasOwnProperty.call(source, key)) {target[key] = source[key];}}}return target;};var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}();var _baseLexer = require('./base-lexer');var _baseLexer2 = _interopRequireDefault(_baseLexer); | ||
var _cheerio = require('cheerio');var _cheerio2 = _interopRequireDefault(_cheerio);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}}function _possibleConstructorReturn(self, call) {if (!self) {throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call && (typeof call === "object" || typeof call === "function") ? call : self;}function _inherits(subClass, superClass) {if (typeof superClass !== "function" && superClass !== null) {throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);}subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;}var | ||
@@ -8,21 +9,22 @@ HTMLLexer = function (_BaseLexer) {_inherits(HTMLLexer, _BaseLexer); | ||
_this.attr = options.attr || 'data-i18n'; | ||
_this.optionAttr = options.optionAttr || 'data-i18n-options'; | ||
_this.optionAttr = options.optionAttr || 'data-i18n-options';return _this; | ||
}_createClass(HTMLLexer, [{ key: 'extract', value: function extract( | ||
_this.createAttributeRegex(); | ||
_this.createOptionAttributeRegex();return _this; | ||
} | ||
content) {var _this2 = this; | ||
var that = this; | ||
var $ = _cheerio2.default.load(content); | ||
$('[' + that.attr + ']').each(function (index, node) { | ||
var $node = _cheerio2.default.load(node); | ||
// TODO rewrite to support the BaseLexer.extract() | ||
_createClass(HTMLLexer, [{ key: 'extract', value: function extract(content) {var _this2 = this; | ||
var matches = void 0; | ||
var regex = new RegExp( | ||
'<([A-Z][A-Z0-9]*)([^>]*\\s' + this.attr + '[^>]*)>(?:((?:\\s|.)*?)<\\/\\1>)?', | ||
'gi');var _loop = function _loop() { | ||
// the attribute can hold multiple keys | ||
var keys = node.attribs[that.attr].split(';'); | ||
var options = node.attribs[that.optionAttr]; | ||
if (options) { | ||
try { | ||
options = JSON.parse(options); | ||
} finally | ||
{} | ||
} | ||
var attrs = _this2.parseAttributes(matches[2]); | ||
// the attribute can hold multiple keys | ||
var keys = attrs.keys.split(';'); | ||
keys.forEach(function (key) { | ||
@@ -33,43 +35,11 @@ // remove any leading [] in the key | ||
// if empty grab innerHTML from regex | ||
key = key || matches[3]; | ||
key = key || $node.text(); | ||
if (key) { | ||
_this2.keys.push(_extends({}, attrs.options, { key: key })); | ||
_this2.keys.push(_extends({}, options, { key: key })); | ||
} | ||
});};while (matches = regex.exec(content)) {_loop(); | ||
} | ||
}); | ||
}); | ||
return this.keys; | ||
} }, { key: 'createAttributeRegex', value: function createAttributeRegex() | ||
{ | ||
var pattern = '(?:' + this.attr + ')(?:\\s*=\\s*(' + _baseLexer2.default.stringPattern + ')|$|\\s)'; | ||
this.attrRegex = new RegExp(pattern, 'i'); | ||
return this.attrRegex; | ||
} }, { key: 'createOptionAttributeRegex', value: function createOptionAttributeRegex() | ||
{ | ||
var pattern = '(?:' + this.optionAttr + ')(?:\\s*=\\s*(' + _baseLexer2.default.stringPattern + '))?'; | ||
this.optionAttrRegex = new RegExp(pattern, 'i'); | ||
return this.optionAttrRegex; | ||
} }, { key: 'parseAttributes', value: function parseAttributes( | ||
args) { | ||
var result = { keys: '', options: {} }; | ||
this.attrRegex.lastIndex = 0; | ||
var keysMatch = this.attrRegex.exec(args); | ||
if (keysMatch && keysMatch[1]) { | ||
result.keys = keysMatch[1].slice(1, -1); | ||
} | ||
this.optionAttrRegex.lastIndex = 0; | ||
var optionsMatch = this.optionAttrRegex.exec(args); | ||
if (optionsMatch && optionsMatch[1]) { | ||
try { | ||
result.options = JSON.parse(optionsMatch[1].slice(1, -1)); | ||
} finally | ||
{} | ||
} | ||
return result; | ||
} }]);return HTMLLexer;}(_baseLexer2.default);exports.default = HTMLLexer;module.exports = exports['default']; |
@@ -46,3 +46,3 @@ 'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _extends = Object.assign || function (target) {for (var i = 1; i < arguments.length; i++) {var source = arguments[i];for (var key in source) {if (Object.prototype.hasOwnProperty.call(source, key)) {target[key] = source[key];}}}return target;};var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}();var _acornJsx = require('acorn-jsx');var acorn = _interopRequireWildcard(_acornJsx); | ||
if (!concatenatedString) { | ||
this.emit('warning', 'Key is not a string litteral: ' + keyArgument.name); | ||
this.emit('warning', 'Key is not a string literal: ' + keyArgument.name); | ||
return; | ||
@@ -54,3 +54,3 @@ } | ||
if (keyArgument.type === 'Identifier') { | ||
this.emit('warning', 'Key is not a string litteral: ' + keyArgument.name); | ||
this.emit('warning', 'Key is not a string literal: ' + keyArgument.name); | ||
} | ||
@@ -57,0 +57,0 @@ |
@@ -9,2 +9,5 @@ 'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _extends = Object.assign || function (target) {for (var i = 1; i < arguments.length; i++) {var source = arguments[i];for (var key in source) {if (Object.prototype.hasOwnProperty.call(source, key)) {target[key] = source[key];}}}return target;};var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}();var _acornJsx = require('acorn-jsx');var acorn = _interopRequireWildcard(_acornJsx); | ||
}, | ||
JSXEmptyExpression: function JSXEmptyExpression(node, st, c) { | ||
// We need this catch, but we don't need the catch to do anything. | ||
}, | ||
JSXElement: function JSXElement(node, st, c) { | ||
@@ -116,5 +119,37 @@ node.openingElement.attributes.forEach(function (attr) {return c(attr, st, attr.type);}); | ||
if (child.type === 'JSXExpressionContainer') { | ||
// strip empty expressions | ||
if (child.expression.type === 'JSXEmptyExpression') | ||
return { | ||
type: 'text', | ||
content: '' | ||
// strip properties from ObjectExpressions | ||
// annoying (and who knows how many other exceptions we'll need to write) but necessary | ||
};else if (child.expression.type === 'ObjectExpression') { | ||
// i18next-react only accepts two props, any random single prop, and a format prop | ||
// for our purposes, format prop is always ignored | ||
var nonFormatProperties = child.expression.properties.filter(function (prop) {return prop.key.name !== 'format';}); | ||
// more than one property throw a warning in i18next-react, but still works as a key | ||
if (nonFormatProperties.length > 1) { | ||
_this2.emit('warning', 'The passed in object contained more than one variable - the object should look like {{ value, format }} where format is optional.'); | ||
return { | ||
type: 'text', | ||
content: '' }; | ||
} | ||
return { | ||
type: 'js', | ||
content: '{{' + nonFormatProperties[0].key.name + '}}' }; | ||
} | ||
// slice on the expression so that we ignore comments around it | ||
return { | ||
type: 'js', | ||
content: originalString.slice(child.start, child.end) }; | ||
content: '{' + originalString.slice(child.expression.start, child.expression.end) + '}' }; | ||
@@ -121,0 +156,0 @@ } else |
@@ -5,3 +5,3 @@ { | ||
"name": "i18next-parser", | ||
"version": "1.0.0-beta13", | ||
"version": "1.0.0-beta14", | ||
"license": "MIT", | ||
@@ -23,2 +23,3 @@ "main": "dist/index.js", | ||
"acorn-jsx": "^4.1.1", | ||
"cheerio": "^1.0.0-rc.2", | ||
"colors": "~1.2.0-rc0", | ||
@@ -25,0 +26,0 @@ "commander": "~2.9.0", |
@@ -71,3 +71,4 @@ import { dotPathToHash, mergeHashes, populateHash } from './helpers' | ||
if (parts.length > 1) { | ||
// make sure we're not pulling a 'namespace' out of a default value | ||
if (parts.length > 1 && key !== entry.defaultValue) { | ||
entry.namespace = parts.shift() | ||
@@ -74,0 +75,0 @@ } |
@@ -10,23 +10,2 @@ import EventEmitter from 'events' | ||
populateKeysFromArguments(args) { | ||
const firstArgument = args.arguments[0] | ||
const secondArgument = args.arguments[1] | ||
const isKeyString = this.validateString(firstArgument) | ||
const isDefaultValueString = this.validateString(secondArgument) | ||
if (!isKeyString) { | ||
this.emit('warning', `Key is not a string litteral: ${firstArgument}`) | ||
} | ||
else { | ||
const result = { | ||
...args.options, | ||
key: firstArgument.slice(1, -1) | ||
} | ||
if (isDefaultValueString) { | ||
result.defaultValue = secondArgument.slice(1, -1) | ||
} | ||
this.keys.push(result) | ||
} | ||
} | ||
validateString(string) { | ||
@@ -33,0 +12,0 @@ const regex = new RegExp('^' + BaseLexer.stringPattern + '$', 'i') |
@@ -41,2 +41,23 @@ import BaseLexer from './base-lexer' | ||
populateKeysFromArguments(args) { | ||
const firstArgument = args.arguments[0] | ||
const secondArgument = args.arguments[1] | ||
const isKeyString = this.validateString(firstArgument) | ||
const isDefaultValueString = this.validateString(secondArgument) | ||
if (!isKeyString) { | ||
this.emit('warning', `Key is not a string literal: ${firstArgument}`) | ||
} | ||
else { | ||
const result = { | ||
...args.options, | ||
key: firstArgument.slice(1, -1) | ||
} | ||
if (isDefaultValueString) { | ||
result.defaultValue = secondArgument.slice(1, -1) | ||
} | ||
this.keys.push(result) | ||
} | ||
} | ||
createFunctionRegex() { | ||
@@ -43,0 +64,0 @@ const functionPattern = this.functionPattern() |
import BaseLexer from './base-lexer' | ||
import cheerio from 'cheerio' | ||
@@ -9,20 +10,21 @@ export default class HTMLLexer extends BaseLexer { | ||
this.optionAttr = options.optionAttr || 'data-i18n-options' | ||
this.createAttributeRegex() | ||
this.createOptionAttributeRegex() | ||
} | ||
// TODO rewrite to support the BaseLexer.extract() | ||
extract(content) { | ||
let matches | ||
const regex = new RegExp( | ||
'<([A-Z][A-Z0-9]*)([^>]*\\s' + this.attr + '[^>]*)>(?:((?:\\s|.)*?)<\\/\\1>)?', | ||
'gi' | ||
) | ||
const that = this | ||
const $ = cheerio.load(content) | ||
$(`[${that.attr}]`).each((index, node) => { | ||
const $node = cheerio.load(node) | ||
while (matches = regex.exec(content)) { | ||
const attrs = this.parseAttributes(matches[2]) | ||
// the attribute can hold multiple keys | ||
const keys = node.attribs[that.attr].split(';') | ||
let options = node.attribs[that.optionAttr] | ||
// the attribute can hold multiple keys | ||
const keys = attrs.keys.split(';') | ||
if (options) { | ||
try { | ||
options = JSON.parse(options) | ||
} | ||
finally {} | ||
} | ||
keys.forEach(key => { | ||
@@ -33,44 +35,12 @@ // remove any leading [] in the key | ||
// if empty grab innerHTML from regex | ||
key = key || matches[3] | ||
key = key || $node.text() | ||
if (key) { | ||
this.keys.push({ ...attrs.options, key }) | ||
this.keys.push({ ...options, key }) | ||
} | ||
}) | ||
} | ||
}) | ||
return this.keys | ||
} | ||
createAttributeRegex() { | ||
const pattern = '(?:' + this.attr + ')(?:\\s*=\\s*(' + BaseLexer.stringPattern + ')|$|\\s)' | ||
this.attrRegex = new RegExp(pattern, 'i') | ||
return this.attrRegex | ||
} | ||
createOptionAttributeRegex() { | ||
const pattern = '(?:' + this.optionAttr + ')(?:\\s*=\\s*(' + BaseLexer.stringPattern + '))?' | ||
this.optionAttrRegex = new RegExp(pattern, 'i') | ||
return this.optionAttrRegex | ||
} | ||
parseAttributes(args) { | ||
const result = { keys: '', options: {} } | ||
this.attrRegex.lastIndex = 0 | ||
let keysMatch = this.attrRegex.exec(args) | ||
if (keysMatch && keysMatch[1]) { | ||
result.keys = keysMatch[1].slice(1, -1) | ||
} | ||
this.optionAttrRegex.lastIndex = 0 | ||
const optionsMatch = this.optionAttrRegex.exec(args) | ||
if (optionsMatch && optionsMatch[1]) { | ||
try { | ||
result.options = JSON.parse(optionsMatch[1].slice(1, -1)) | ||
} | ||
finally {} | ||
} | ||
return result | ||
} | ||
} |
@@ -46,3 +46,3 @@ import * as acorn from 'acorn-jsx' | ||
if (!concatenatedString) { | ||
this.emit('warning', `Key is not a string litteral: ${keyArgument.name}`) | ||
this.emit('warning', `Key is not a string literal: ${keyArgument.name}`) | ||
return | ||
@@ -54,3 +54,3 @@ } | ||
if (keyArgument.type === 'Identifier') { | ||
this.emit('warning', `Key is not a string litteral: ${keyArgument.name}`) | ||
this.emit('warning', `Key is not a string literal: ${keyArgument.name}`) | ||
} | ||
@@ -57,0 +57,0 @@ |
@@ -9,2 +9,5 @@ import * as acorn from 'acorn-jsx' | ||
}, | ||
JSXEmptyExpression(node, st, c) { | ||
// We need this catch, but we don't need the catch to do anything. | ||
}, | ||
JSXElement(node, st, c) { | ||
@@ -59,3 +62,3 @@ node.openingElement.attributes.forEach(attr => c(attr, st, attr.type)) | ||
if (!entry.key) | ||
entry.key = entry.defaultValue | ||
entry.key = entry.defaultValue | ||
} | ||
@@ -117,5 +120,37 @@ | ||
else if (child.type === 'JSXExpressionContainer') { | ||
// strip empty expressions | ||
if (child.expression.type === 'JSXEmptyExpression') | ||
return { | ||
type: 'text', | ||
content: '' | ||
} | ||
// strip properties from ObjectExpressions | ||
// annoying (and who knows how many other exceptions we'll need to write) but necessary | ||
else if (child.expression.type === 'ObjectExpression') { | ||
// i18next-react only accepts two props, any random single prop, and a format prop | ||
// for our purposes, format prop is always ignored | ||
let nonFormatProperties = child.expression.properties.filter(prop => prop.key.name !== 'format') | ||
// more than one property throw a warning in i18next-react, but still works as a key | ||
if (nonFormatProperties.length > 1) { | ||
this.emit('warning', `The passed in object contained more than one variable - the object should look like {{ value, format }} where format is optional.`) | ||
return { | ||
type: 'text', | ||
content: '' | ||
} | ||
} | ||
return { | ||
type: 'js', | ||
content: `{{${nonFormatProperties[0].key.name}}}` | ||
} | ||
} | ||
// slice on the expression so that we ignore comments around it | ||
return { | ||
type: 'js', | ||
content: originalString.slice(child.start, child.end) | ||
content: `{${originalString.slice(child.expression.start, child.expression.end)}}` | ||
} | ||
@@ -122,0 +157,0 @@ } |
@@ -81,49 +81,2 @@ import { assert } from 'chai' | ||
}) | ||
describe('parseAttributes()', () => { | ||
it('extracts attribute value from string', (done) => { | ||
const Lexer = new HTMLLexer() | ||
assert.deepEqual( | ||
Lexer.parseAttributes('title="" bla data-i18n="key1"', 'data-i18n'), | ||
{ | ||
keys: 'key1', | ||
options: {} | ||
} | ||
) | ||
done() | ||
}) | ||
it('extracts json strings too', (done) => { | ||
const Lexer = new HTMLLexer() | ||
assert.deepEqual( | ||
Lexer.parseAttributes( | ||
'data-i18n="key1;key2" data-i18n-options=\'{"defaultValue": "bla"}\'', | ||
'data-i18n-options' | ||
), | ||
{ | ||
keys: 'key1;key2', | ||
options: { | ||
defaultValue: 'bla' | ||
} | ||
} | ||
) | ||
done() | ||
}) | ||
it('supports multiline', (done) => { | ||
const Lexer = new HTMLLexer() | ||
assert.deepEqual( | ||
Lexer.parseAttributes( | ||
'title=""\n bla\n data-i18n="first"\n data-i18n-options=\'{"defaultValue": "bar"}\'' | ||
), | ||
{ | ||
keys: 'first', | ||
options: { | ||
defaultValue: 'bar' | ||
} | ||
} | ||
) | ||
done() | ||
}) | ||
}) | ||
}) |
@@ -62,2 +62,20 @@ import { assert } from 'chai' | ||
it('extracts keys from Trans elements and ignores values of expressions and spaces', (done) => { | ||
const Lexer = new JsxLexer() | ||
const content = '<Trans count={count}>{{ key: property }}</Trans>' | ||
assert.deepEqual(Lexer.extract(content), [ | ||
{ key: '<0>{{key}}</0>', defaultValue: '<0>{{key}}</0>' } | ||
]) | ||
done() | ||
}) | ||
it('invalid interpolation gets stripped', (done) => { | ||
const Lexer = new JsxLexer() | ||
const content = '<Trans count={count}>before{{ key1, key2 }}after</Trans>' | ||
assert.deepEqual(Lexer.extract(content), [ | ||
{ key: 'beforeafter', defaultValue: 'beforeafter' } | ||
]) | ||
done() | ||
}) | ||
it('doesn\'t add a blank key for self-closing or empty tags', (done) => { | ||
@@ -81,3 +99,10 @@ const Lexer = new JsxLexer() | ||
}) | ||
it('erases comment expressions', (done) => { | ||
const Lexer = new JsxLexer() | ||
const content = '<Trans>{/* some comment */}Some Content</Trans>' | ||
assert.equal(Lexer.extract(content)[0].defaultValue, 'Some Content') | ||
done() | ||
}) | ||
}) | ||
}) |
@@ -93,3 +93,4 @@ import { assert } from 'chai' | ||
fifth: 'bar', | ||
sixth: '' | ||
sixth: '', | ||
selfClosing: '' | ||
} | ||
@@ -194,3 +195,5 @@ | ||
bar: '', | ||
foo: '' | ||
foo: '', | ||
"This should be part of the value and the key": "This should be part of the value and the key", | ||
"don't split <1>{{on}}</1>": "don't split <1>{{on}}</1>" | ||
} | ||
@@ -586,3 +589,5 @@ | ||
bar: '', | ||
foo: '' | ||
foo: '', | ||
"This should be part of the value and the key": "This should be part of the value and the key", | ||
"don't split <1>{{on}}</1>": "don't split <1>{{on}}</1>" | ||
} | ||
@@ -826,3 +831,3 @@ | ||
i18nextParser.on('warning', message => { | ||
assert.equal(message, 'Key is not a string litteral: variable') | ||
assert.equal(message, 'Key is not a string literal: variable') | ||
done() | ||
@@ -832,3 +837,17 @@ }) | ||
}) | ||
it('emits a `warning` event if a react value contains two variables', (done) => { | ||
const i18nextParser = new i18nTransform({ output: 'test/locales' }) | ||
const fakeFile = new Vinyl({ | ||
contents: Buffer.from('<Trans>{{ key1, key2 }}</Trans>'), | ||
path: 'file.js' | ||
}) | ||
i18nextParser.on('warning', message => { | ||
assert.equal(message, 'The passed in object contained more than one variable - the object should look like {{ value, format }} where format is optional.') | ||
done() | ||
}) | ||
i18nextParser.end(fakeFile) | ||
}) | ||
}) | ||
}) |
@@ -33,2 +33,9 @@ import React from 'react' | ||
</Trans> | ||
<Trans> | ||
This should be part of the value and the key | ||
{/* this shouldn't */} | ||
</Trans> | ||
<Trans> | ||
don't split {{ on: this }} | ||
</Trans> | ||
</div> | ||
@@ -35,0 +42,0 @@ ) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
403958
62
3237
13
+ Addedcheerio@^1.0.0-rc.2
+ Addedboolbase@1.0.0(transitive)
+ Addedcheerio@1.0.0(transitive)
+ Addedcheerio-select@2.1.0(transitive)
+ Addedcss-select@5.1.0(transitive)
+ Addedcss-what@6.1.0(transitive)
+ Addeddom-serializer@2.0.0(transitive)
+ Addeddomelementtype@2.3.0(transitive)
+ Addeddomhandler@5.0.3(transitive)
+ Addeddomutils@3.2.2(transitive)
+ Addedencoding-sniffer@0.2.0(transitive)
+ Addedentities@4.5.0(transitive)
+ Addedhtmlparser2@9.1.0(transitive)
+ Addediconv-lite@0.6.3(transitive)
+ Addednth-check@2.1.1(transitive)
+ Addedparse5@7.2.1(transitive)
+ Addedparse5-htmlparser2-tree-adapter@7.1.0(transitive)
+ Addedparse5-parser-stream@7.1.2(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedundici@6.21.1(transitive)
+ Addedwhatwg-encoding@3.1.1(transitive)
+ Addedwhatwg-mimetype@4.0.0(transitive)