diff --git a/src/helpers.js b/src/helpers.js index 570bad45..5d067954 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -260,6 +260,40 @@ function makeDefaultSort(pluralSeparator) { } } +// unescape common html entities +// code from react-18next taken from +// https://github.com/i18next/react-i18next/blob/d3247b5c232f5d8c1a154fe5dd0090ca88c82dcf/src/unescape.js +function unescape(text) { + const matchHtmlEntity = + /&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34|nbsp|#160|copy|#169|reg|#174|hellip|#8230|#x2F|#47);/g + const htmlEntities = { + '&': '&', + '&': '&', + '<': '<', + '<': '<', + '>': '>', + '>': '>', + ''': "'", + ''': "'", + '"': '"', + '"': '"', + ' ': ' ', + ' ': ' ', + '©': '©', + '©': '©', + '®': '®', + '®': '®', + '…': '…', + '…': '…', + '/': '/', + '/': '/', + } + + const unescapeHtmlEntity = (m) => htmlEntities[m] + + return text.replace(matchHtmlEntity, unescapeHtmlEntity) +} + export { dotPathToHash, mergeHashes, @@ -268,4 +302,5 @@ export { getSingularForm, getPluralSuffixPosition, makeDefaultSort, + unescape, } diff --git a/src/lexers/jsx-lexer.js b/src/lexers/jsx-lexer.js index eba68964..0546e8a8 100644 --- a/src/lexers/jsx-lexer.js +++ b/src/lexers/jsx-lexer.js @@ -1,5 +1,6 @@ import JavascriptLexer from './javascript-lexer.js' import ts from 'typescript' +import { unescape } from '../helpers.js' export default class JsxLexer extends JavascriptLexer { constructor(options = {}) { @@ -91,18 +92,6 @@ export default class JsxLexer extends JavascriptLexer { const entry = {} entry.key = getKey(tagNode) - const defaultsProp = getPropValue(tagNode, 'defaults') - const defaultValue = - defaultsProp || this.nodeToString.call(this, node, sourceText) - - if (defaultValue !== '') { - entry.defaultValue = defaultValue - - if (!entry.key) { - entry.key = entry.defaultValue - } - } - const namespace = getPropValue(tagNode, 'ns') if (namespace) { entry.namespace = namespace @@ -143,6 +132,22 @@ export default class JsxLexer extends JavascriptLexer { } else entry[property.name.text] = true }) + const defaultsProp = getPropValue(tagNode, 'defaults') + let defaultValue = + defaultsProp || this.nodeToString.call(this, node, sourceText) + + if (entry.shouldUnescape === true) { + defaultValue = unescape(defaultValue) + } + + if (defaultValue !== '') { + entry.defaultValue = defaultValue + + if (!entry.key) { + entry.key = entry.defaultValue + } + } + return entry.key ? entry : null } else if (tagNode.tagName.text === 'Interpolate') { const entry = {} diff --git a/test/lexers/jsx-lexer.test.js b/test/lexers/jsx-lexer.test.js index 41cf7744..b3f4dede 100644 --- a/test/lexers/jsx-lexer.test.js +++ b/test/lexers/jsx-lexer.test.js @@ -314,7 +314,7 @@ describe('JsxLexer', () => { done() }) - it('invalid interpolation gets stripped', (done) => { + it('strips invalid interpolation', (done) => { const Lexer = new JsxLexer() const content = 'before{{ key1, key2 }}after' @@ -379,6 +379,16 @@ describe('JsxLexer', () => { ) done() }) + + it('supports the shouldUnescape options', (done) => { + const Lexer = new JsxLexer() + const content = 'I&apros;m Cielquan' + assert.equal( + Lexer.extract(content)[0].defaultValue, + 'I&apros;m Cielquan' + ) + done() + }) }) }) })