From 8987fc726ad0ef842ee669a40c033fb836f19bf5 Mon Sep 17 00:00:00 2001 From: Eugene Zhlobo Date: Mon, 12 Feb 2018 22:40:37 +0300 Subject: [PATCH] Handle shorthands in attributes correctly --- .../attributes-shorthand.test.js.snap | 16 ++++++ src/__tests__/attributes-shorthand.input.js | 16 ++++++ src/__tests__/attributes-shorthand.test.js | 3 ++ src/__tests__/attributes-unescaped.test.js | 49 +++++++++++++++++++ src/visitors/Tag.js | 14 +++++- 5 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 src/__tests__/__snapshots__/attributes-shorthand.test.js.snap create mode 100644 src/__tests__/attributes-shorthand.input.js create mode 100644 src/__tests__/attributes-shorthand.test.js create mode 100644 src/__tests__/attributes-unescaped.test.js diff --git a/src/__tests__/__snapshots__/attributes-shorthand.test.js.snap b/src/__tests__/__snapshots__/attributes-shorthand.test.js.snap new file mode 100644 index 0000000..54278bb --- /dev/null +++ b/src/__tests__/__snapshots__/attributes-shorthand.test.js.snap @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`JavaScript output: transformed source code 1`] = ` +"'use strict'; + +// To prevent warnings in console from react + +const Custom = () => null; +const test = 10; + +module.exports = ;" +`; + +exports[`html output: generated html 1`] = `null`; + +exports[`static html output: static html 1`] = `""`; diff --git a/src/__tests__/attributes-shorthand.input.js b/src/__tests__/attributes-shorthand.input.js new file mode 100644 index 0000000..b83d652 --- /dev/null +++ b/src/__tests__/attributes-shorthand.input.js @@ -0,0 +1,16 @@ +'use strict'; + +// To prevent warnings in console from react +const Custom = () => null +const test = 10 + +module.exports = pug` + Custom( + first-attribute + second-attribute + positive=true + negative=false + check + ) + Custom(one two) +`; diff --git a/src/__tests__/attributes-shorthand.test.js b/src/__tests__/attributes-shorthand.test.js new file mode 100644 index 0000000..e7b91de --- /dev/null +++ b/src/__tests__/attributes-shorthand.test.js @@ -0,0 +1,3 @@ +import testHelper from './test-helper'; + +testHelper(__dirname + '/attributes-shorthand.input.js'); diff --git a/src/__tests__/attributes-unescaped.test.js b/src/__tests__/attributes-unescaped.test.js new file mode 100644 index 0000000..87e8f82 --- /dev/null +++ b/src/__tests__/attributes-unescaped.test.js @@ -0,0 +1,49 @@ +import React from 'react'; +import {transform} from 'babel-core'; +import renderer from 'react-test-renderer'; +import transformReactPug from '../'; + +const transformationOptions = { + babelrc: false, + plugins: [transformReactPug], +} + +const transformer = (code) => { + return transform(`pug\`${code}\``, transformationOptions).code +} + +const ExpectedError = /Unescaped attributes/ + +test('throws error when pass string', () => { + const wrapped = () => transformer(` + div(name!="hello") + `) + + expect(wrapped).toThrowError(ExpectedError) +}) + +test('throws error when pass variable', () => { + const wrapped = () => transformer(` + - const variable = 'value' + div(name!=variable.toString()) + `) + + expect(wrapped).toThrowError(ExpectedError) +}) + +test('does not throw error when pass variable or just string', () => { + const wrapped = () => transformer(` + - const variable = 'value' + div(data-string="hello" data-variable=variable) + `) + + expect(wrapped).not.toThrowError(ExpectedError) +}) + +test('does not throw error when pass boolean variables', () => { + const wrapped = () => transformer(` + div(data-first data-second data-third) + `) + + expect(wrapped).not.toThrowError(ExpectedError) +}) diff --git a/src/visitors/Tag.js b/src/visitors/Tag.js index 705bb74..5f9d714 100644 --- a/src/visitors/Tag.js +++ b/src/visitors/Tag.js @@ -38,6 +38,16 @@ function getAttributes( ): Array { const classes = []; const attrs = node.attrs + .map((node) => { + if (node.val === true) { + return { + ...node, + mustEscape: false, + } + } + + return node + }) .map(({name, val, mustEscape}) => { if (/\.\.\./.test(name) && val === true) { return t.jSXSpreadAttribute(parseExpression(name.substr(3), context)); @@ -57,8 +67,8 @@ function getAttributes( const expr = parseExpression(val === true ? 'true' : val, context); - if (!mustEscape && (!t.isStringLiteral(expr) || /(\<\>\&)/.test(val))) { - throw new Error('Unescaped attributes are not supported in react-pug'); + if (!mustEscape && val !== true) { + throw new Error('Unescaped attributes are not supported in react-pug') } if (expr == null) {