i18next-parser
Advanced tools
Comparing version
# Changelog | ||
## 1.0.0-beta8 - latest | ||
## 1.0.0-beta9 - latest | ||
- See [release](https://github.com/i18next/i18next-parser/releases/tag/1.0.0-beta9) | ||
## 1.0.0-beta8 | ||
- See [release](https://github.com/i18next/i18next-parser/releases/tag/1.0.0-beta8) | ||
@@ -6,0 +10,0 @@ |
@@ -1,2 +0,2 @@ | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.populateHash = exports.mergeHashes = exports.dotPathToHash = undefined;var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {return typeof obj;} : function (obj) {return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;};var _lodash = require('lodash');var _lodash2 = _interopRequireDefault(_lodash);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.ParsingError = exports.populateHash = exports.mergeHashes = exports.dotPathToHash = undefined;var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {return typeof obj;} : function (obj) {return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;};var _lodash = require('lodash');var _lodash2 = _interopRequireDefault(_lodash);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;} | ||
@@ -106,8 +106,15 @@ // Turn an entry for the Parser and turn in into a hash, | ||
return target; | ||
}exports. | ||
}var | ||
ParsingError = function (_Error) {_inherits(ParsingError, _Error); | ||
function ParsingError(message) {_classCallCheck(this, ParsingError);var _this = _possibleConstructorReturn(this, (ParsingError.__proto__ || Object.getPrototypeOf(ParsingError)).call(this, | ||
message)); | ||
_this.name = 'ParsingError';return _this; | ||
}return ParsingError;}(Error);exports. | ||
dotPathToHash = dotPathToHash;exports. | ||
mergeHashes = mergeHashes;exports. | ||
populateHash = populateHash; | ||
populateHash = populateHash;exports. | ||
ParsingError = ParsingError; |
@@ -1,2 +0,6 @@ | ||
'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 _htmlLexer = require('./html-lexer');var _htmlLexer2 = _interopRequireDefault(_htmlLexer);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 _acornJsx = require('acorn-jsx');var acorn = _interopRequireWildcard(_acornJsx); | ||
var _assert = require('assert');var _assert2 = _interopRequireDefault(_assert); | ||
var _htmlLexer = require('./html-lexer');var _htmlLexer2 = _interopRequireDefault(_htmlLexer); | ||
var _baseLexer = require('./base-lexer');var _baseLexer2 = _interopRequireDefault(_baseLexer); | ||
var _helpers = require('../helpers');function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}function _interopRequireWildcard(obj) {if (obj && obj.__esModule) {return obj;} else {var newObj = {};if (obj != null) {for (var key in obj) {if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key];}}newObj.default = obj;return newObj;}}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 | ||
@@ -47,3 +51,3 @@ JsxLexer = function (_HTMLLexer) {_inherits(JsxLexer, _HTMLLexer); | ||
if (matches[3] && !attrs.options.defaultValue) { | ||
attrs.options.defaultValue = matches[3].trim(); | ||
attrs.options.defaultValue = this.eraseTags(matches[0]).replace(/\s+/g, ' '); | ||
} | ||
@@ -57,2 +61,56 @@ | ||
return this.keys; | ||
} | ||
/** | ||
* Recursively convert html tags and js injections to tags with the child index in it | ||
* @param {string} string | ||
* | ||
* @returns string | ||
*/ }, { key: 'eraseTags', value: function eraseTags( | ||
string) { | ||
var acornAst = acorn.parse(string, { plugins: { jsx: true } }); | ||
var acornTransAst = acornAst.body[0].expression; | ||
var children = this.parseAcornPayload(acornTransAst.children, string); | ||
var elemsToString = function elemsToString(children) {return children.map(function (child, index) { | ||
switch (child.type) { | ||
case 'text':return child.content; | ||
case 'js':return '<' + index + '>' + child.content + '</' + index + '>'; | ||
case 'tag':return '<' + index + '>' + elemsToString(child.children) + '</' + index + '>'; | ||
default:throw new _helpers.ParsingError('Unknown parsed content: ' + child.type);} | ||
}).join('');}; | ||
return elemsToString(children); | ||
} | ||
/** | ||
* Simplify the bulky AST given by Acorn | ||
* @param {*} children An array of elements contained inside an html tag | ||
* @param {string} originalString The original string being parsed | ||
*/ }, { key: 'parseAcornPayload', value: function parseAcornPayload( | ||
children, originalString) {var _this2 = this; | ||
return children.map(function (child) { | ||
if (child.type === 'JSXText') { | ||
return { | ||
type: 'text', | ||
content: child.value.replace(/^(?:\s*(\n|\r)\s*)?(.*)(?:\s*(\n|\r)\s*)?$/, '$2') }; | ||
} else | ||
if (child.type === 'JSXElement') { | ||
return { | ||
type: 'tag', | ||
children: _this2.parseAcornPayload(child.children, originalString) }; | ||
} else | ||
if (child.type === 'JSXExpressionContainer') { | ||
return { | ||
type: 'js', | ||
content: originalString.slice(child.start, child.end) }; | ||
} else | ||
{ | ||
throw new _helpers.ParsingError('Unknown ast element when parsing jsx: ' + child.type); | ||
} | ||
}).filter(function (child) {return child.type !== 'text' || child.content;}); | ||
} }]);return JsxLexer;}(_htmlLexer2.default);exports.default = JsxLexer; |
@@ -5,3 +5,3 @@ { | ||
"name": "i18next-parser", | ||
"version": "1.0.0-beta8", | ||
"version": "1.0.0-beta9", | ||
"license": "MIT", | ||
@@ -21,2 +21,3 @@ "main": "src/index.js", | ||
"dependencies": { | ||
"acorn-jsx": "^4.1.1", | ||
"colors": "~1.2.0-rc0", | ||
@@ -23,0 +24,0 @@ "commander": "~2.9.0", |
@@ -108,2 +108,8 @@ import _ from 'lodash' | ||
class ParsingError extends Error { | ||
constructor(message) { | ||
super(message); | ||
this.name = 'ParsingError'; | ||
} | ||
} | ||
@@ -113,3 +119,4 @@ export { | ||
mergeHashes, | ||
populateHash | ||
populateHash, | ||
ParsingError | ||
} |
@@ -0,2 +1,6 @@ | ||
import * as acorn from 'acorn-jsx' | ||
import assert from 'assert' | ||
import HTMLLexer from './html-lexer' | ||
import BaseLexer from './base-lexer' | ||
import { ParsingError } from '../helpers' | ||
@@ -47,3 +51,3 @@ export default class JsxLexer extends HTMLLexer { | ||
if (matches[3] && !attrs.options.defaultValue) { | ||
attrs.options.defaultValue = matches[3].trim() | ||
attrs.options.defaultValue = this.eraseTags(matches[0]).replace(/\s+/g, ' ') | ||
} | ||
@@ -58,2 +62,56 @@ | ||
} | ||
/** | ||
* Recursively convert html tags and js injections to tags with the child index in it | ||
* @param {string} string | ||
* | ||
* @returns string | ||
*/ | ||
eraseTags(string) { | ||
const acornAst = acorn.parse(string, {plugins: {jsx: true}}) | ||
const acornTransAst = acornAst.body[0].expression | ||
const children = this.parseAcornPayload(acornTransAst.children, string) | ||
const elemsToString = children => children.map((child, index) => { | ||
switch(child.type) { | ||
case 'text': return child.content | ||
case 'js': return `<${index}>${child.content}</${index}>` | ||
case 'tag': return `<${index}>${elemsToString(child.children)}</${index}>` | ||
default: throw new ParsingError('Unknown parsed content: ' + child.type) | ||
} | ||
}).join('') | ||
return elemsToString(children) | ||
} | ||
/** | ||
* Simplify the bulky AST given by Acorn | ||
* @param {*} children An array of elements contained inside an html tag | ||
* @param {string} originalString The original string being parsed | ||
*/ | ||
parseAcornPayload(children, originalString) { | ||
return children.map(child => { | ||
if (child.type === 'JSXText') { | ||
return { | ||
type: 'text', | ||
content: child.value.replace(/^(?:\s*(\n|\r)\s*)?(.*)(?:\s*(\n|\r)\s*)?$/, '$2') | ||
} | ||
} | ||
else if (child.type === 'JSXElement') { | ||
return { | ||
type: 'tag', | ||
children: this.parseAcornPayload(child.children, originalString) | ||
} | ||
} | ||
else if (child.type === 'JSXExpressionContainer') { | ||
return { | ||
type: 'js', | ||
content: originalString.slice(child.start, child.end) | ||
} | ||
} | ||
else { | ||
throw new ParsingError('Unknown ast element when parsing jsx: ' + child.type) | ||
} | ||
}).filter(child => child.type !== 'text' || child.content) | ||
} | ||
} |
@@ -35,2 +35,11 @@ import { assert } from 'chai' | ||
}) | ||
describe('eraseTags()', () => { | ||
it('erases tags from content', (done) => { | ||
const Lexer = new JsxLexer() | ||
const content = '<Trans>a<b test={"</b>"}>c<c>z</c></b>{d}<br stuff={y}/></Trans>' | ||
assert.equal(Lexer.eraseTags(content), 'a<1>c<1>z</1></1><2>{d}</2><3></3>') | ||
done() | ||
}) | ||
}) | ||
}) |
@@ -186,3 +186,5 @@ import { assert } from 'chai' | ||
third: { | ||
first: 'Hello <strong title={t(\'fourth\')}>{{name}}</strong>, you have {{count}} unread message. <Link to="/msgs">Go to messages</Link>.' | ||
first: 'Hello <1><0>{{name}}</0></1>, you have <3>{{count}}</3> unread message. <5>Go to messages</5>.', | ||
second: ' <1>Hello,</1> this shouldn\'t be trimmed.', | ||
third: '<0>Hello,</0>this should be trimmed.<2> and this shoudln\'t</2>' | ||
}, | ||
@@ -576,3 +578,5 @@ fourth: '', | ||
third: { | ||
first: 'Hello <strong title={t(\'fourth\')}>{{name}}</strong>, you have {{count}} unread message. <Link to="/msgs">Go to messages</Link>.' | ||
first: 'Hello <1><0>{{name}}</0></1>, you have <3>{{count}}</3> unread message. <5>Go to messages</5>.', | ||
second: ' <1>Hello,</1> this shouldn\'t be trimmed.', | ||
third: '<0>Hello,</0>this should be trimmed.<2> and this shoudln\'t</2>' | ||
}, | ||
@@ -579,0 +583,0 @@ fourth: '', |
@@ -24,5 +24,11 @@ import React from 'react' | ||
<Trans i18nKey="third.first" count={count}> | ||
Hello <strong title={t('fourth')}>{{name}}</strong>, you have {{count}} unread message. <Link to="/msgs">Go to messages</Link>. | ||
Hello <strong title={t('fourth')}>{{name}}</strong>, you have {{count}} unread message. <Link to="/msgs">Go to messages</Link>. | ||
</Trans> | ||
<span><Trans i18nKey="fifth" count={count} /></span> | ||
<Trans i18nKey="third.second"> <b>Hello,</b> this shouldn't be trimmed.</Trans> | ||
<Trans i18nKey="third.third"> | ||
<b>Hello,</b> | ||
this should be trimmed. | ||
<i> and this shoudln't</i> | ||
</Trans> | ||
</div> | ||
@@ -29,0 +35,0 @@ ) |
Sorry, the diff of this file is not supported yet
218058
3.48%3208
4.53%11
10%+ Added
+ Added
+ Added