diff --git a/package-lock.json b/package-lock.json
index 4fd3b46c..290f10a1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,9 +1,22 @@
{
"name": "i18next-parser",
- "version": "1.0.0-beta4",
+ "version": "1.0.0-beta8",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
+ "acorn": {
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz",
+ "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ=="
+ },
+ "acorn-jsx": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz",
+ "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==",
+ "requires": {
+ "acorn": "5.5.3"
+ }
+ },
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
@@ -19,7 +32,7 @@
"anymatch": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
- "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
+ "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=",
"dev": true,
"optional": true,
"requires": {
@@ -38,7 +51,7 @@
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=",
"requires": {
"sprintf-js": "1.0.3"
}
@@ -56,7 +69,7 @@
"arr-flatten": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
- "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+ "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=",
"dev": true,
"optional": true
},
@@ -774,7 +787,7 @@
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=",
"requires": {
"balanced-match": "1.0.0",
"concat-map": "0.0.1"
@@ -795,13 +808,13 @@
"browser-stdout": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
- "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+ "integrity": "sha1-uqVZ7hTO1zRSIputcyZGfGH6vWA=",
"dev": true
},
"browserslist": {
"version": "2.11.3",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz",
- "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==",
+ "integrity": "sha1-/jYWeu0bvN5IJ+v+cTR6LMcLmbI=",
"dev": true,
"requires": {
"caniuse-lite": "1.0.30000814",
@@ -925,7 +938,7 @@
"colors": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.2.1.tgz",
- "integrity": "sha512-s8+wktIuDSLffCywiwSxQOMqtPxML11a/dtHE17tMn4B1MSWw/C22EKf7M2KGUBcDaVFEGT+S8N02geDXeuNKg=="
+ "integrity": "sha1-9KPTApdqrwQjVroa3jsaLGLZ15Q="
},
"commander": {
"version": "2.9.0",
@@ -978,7 +991,7 @@
"deep-eql": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
- "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
+ "integrity": "sha1-38lARACtHI/gI+faHfHBR8S0RN8=",
"dev": true,
"requires": {
"type-detect": "4.0.8"
@@ -1005,13 +1018,13 @@
"diff": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
- "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+ "integrity": "sha1-gAwN0eCov7yVg1wgKtIg/jF+WhI=",
"dev": true
},
"duplexify": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.4.tgz",
- "integrity": "sha512-JzYSLYMhoVVBe8+mbHQ4KgpvHpm0DZpJuL8PY93Vyv1fW7jYJ90LoXa1di/CVbJM+TgMs91rbDapE/RNIfnJsA==",
+ "integrity": "sha1-S7RsF5bqvr7sTKmi5muAjLej2LQ=",
"requires": {
"end-of-stream": "1.4.1",
"inherits": "2.0.3",
@@ -1036,7 +1049,7 @@
"eol": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/eol/-/eol-0.9.1.tgz",
- "integrity": "sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg=="
+ "integrity": "sha1-9wGRL1BAdL41xhF6XEreSc1Ues0="
},
"escape-string-regexp": {
"version": "1.0.5",
@@ -1158,7 +1171,7 @@
"fs-readdir-recursive": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
- "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==",
+ "integrity": "sha1-4y/AMKLM7kSmtTcTCNpUvgs5fSc=",
"dev": true
},
"fs.realpath": {
@@ -2084,7 +2097,7 @@
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
- "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+ "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
"requires": {
"fs.realpath": "1.0.0",
"inflight": "1.0.6",
@@ -2177,7 +2190,7 @@
"growl": {
"version": "1.10.3",
"resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz",
- "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==",
+ "integrity": "sha1-GSa6kM8+3+KttJJ/WIC8IsZseQ8=",
"dev": true
},
"gulp-sort": {
@@ -2241,7 +2254,7 @@
"invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
- "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "integrity": "sha1-YQ88ksk1nOHbYW5TgAjSP/NRWOY=",
"dev": true,
"requires": {
"loose-envify": "1.3.1"
@@ -2380,7 +2393,7 @@
"is-windows": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
- "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="
+ "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0="
},
"isarray": {
"version": "1.0.0",
@@ -2510,7 +2523,7 @@
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
- "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
"requires": {
"brace-expansion": "1.1.11"
}
@@ -2744,12 +2757,12 @@
"process-nextick-args": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
- "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
+ "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o="
},
"pump": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
- "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+ "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=",
"requires": {
"end-of-stream": "1.4.1",
"once": "1.4.0"
@@ -2758,7 +2771,7 @@
"pumpify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz",
- "integrity": "sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==",
+ "integrity": "sha1-gLfF334kFT0D8OesigWl0Gi9B/s=",
"requires": {
"duplexify": "3.5.4",
"inherits": "2.0.3",
@@ -2768,7 +2781,7 @@
"randomatic": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
- "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==",
+ "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=",
"dev": true,
"optional": true,
"requires": {
@@ -2813,7 +2826,7 @@
"readable-stream": {
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz",
- "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==",
+ "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
@@ -2863,7 +2876,7 @@
"regex-cache": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
- "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
+ "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=",
"dev": true,
"optional": true,
"requires": {
@@ -2907,7 +2920,7 @@
"remove-bom-buffer": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz",
- "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==",
+ "integrity": "sha1-wr8eN3Ug0yT2I4kuM8EMrCwlK1M=",
"requires": {
"is-buffer": "1.1.6",
"is-utf8": "0.2.1"
@@ -2966,12 +2979,12 @@
"safe-buffer": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
- "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
+ "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM="
},
"semver": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
- "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+ "integrity": "sha1-3Eu8emyp2Rbe5dQ1FvAJK1j3uKs=",
"dev": true
},
"set-immediate-shim": {
@@ -3015,7 +3028,7 @@
"string_decoder": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
- "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
"requires": {
"safe-buffer": "5.1.1"
}
@@ -3149,7 +3162,7 @@
"vinyl-fs": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.2.tgz",
- "integrity": "sha512-AUSFda1OukBwuLPBTbyuO4IRWgfXmqC4UTW0f8xrCa8Hkv9oyIU+NSqBlgfOLZRoUt7cHdo75hKQghCywpIyIw==",
+ "integrity": "sha1-G4YliEQ4P1dYH8qsCB/gnvbW11I=",
"requires": {
"fs-mkdirp-stream": "1.0.0",
"glob-stream": "6.1.0",
@@ -3197,7 +3210,7 @@
"yamljs": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz",
- "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==",
+ "integrity": "sha1-3AYL8mdEezn3ME6bK/votafdsDs=",
"requires": {
"argparse": "1.0.10",
"glob": "7.1.2"
diff --git a/package.json b/package.json
index b3dc27b2..0128e48c 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"url": "https://github.com/i18next/i18next-parser"
},
"dependencies": {
+ "acorn-jsx": "^4.1.1",
"colors": "~1.2.0-rc0",
"commander": "~2.9.0",
"concat-stream": "~1.6.0",
diff --git a/src/helpers.js b/src/helpers.js
index bc957132..a9ab40b7 100644
--- a/src/helpers.js
+++ b/src/helpers.js
@@ -105,9 +105,16 @@ function populateHash(source, target = {}) {
return target
}
+class ParsingError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "ParsingError";
+ }
+}
export {
dotPathToHash,
mergeHashes,
- populateHash
+ populateHash,
+ ParsingError
}
diff --git a/src/lexers/jsx-lexer.js b/src/lexers/jsx-lexer.js
index a342966b..add003fe 100644
--- a/src/lexers/jsx-lexer.js
+++ b/src/lexers/jsx-lexer.js
@@ -1,4 +1,8 @@
+import * as acorn from 'acorn-jsx';
+import assert from 'assert'
import HTMLLexer from './html-lexer'
+import BaseLexer from './base-lexer';
+import { ParsingError } from '../helpers';
export default class JsxLexer extends HTMLLexer {
constructor(options = {}) {
@@ -44,7 +48,7 @@ export default class JsxLexer extends HTMLLexer {
const key = attrs.keys
if (matches[3] && !attrs.options.defaultValue) {
- attrs.options.defaultValue = matches[3].trim()
+ attrs.options.defaultValue = this.eraseTags(matches[0]).replace(/\s+/g, ' ')
}
if (key) {
@@ -54,4 +58,54 @@ export default class JsxLexer extends HTMLLexer {
return this.keys
}
+
+ /**
+ * 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 => {
+ switch (child.type) {
+ case 'JSXText': return {
+ type: 'text',
+ content: child.value.replace(/^(?:\s*(\n|\r)\s*)?(.*)(?:\s*(\n|\r)\s*)?$/, '$2')
+ };
+ case 'JSXElement': return {
+ type: 'tag',
+ children: this.parseAcornPayload(child.children, originalString)
+ };
+ case 'JSXExpressionContainer': return {
+ type: 'js',
+ content: originalString.slice(child.start, child.end)
+ };
+ default: throw new ParsingError("Unknown ast element when parsing jsx: " + child.type)
+ }
+ // Remove empty text elements
+ }).filter(child => child.type !== 'text' || child.content);
+ }
}
diff --git a/test/lexers/jsx-lexer.test.js b/test/lexers/jsx-lexer.test.js
index 8db9257c..a1c147f3 100644
--- a/test/lexers/jsx-lexer.test.js
+++ b/test/lexers/jsx-lexer.test.js
@@ -31,5 +31,12 @@ describe('JsxLexer', () => {
])
done()
})
+
+ it('erases tags from content', done => {
+ const Lexer = new JsxLexer()
+ const content = '