Git Product home page Git Product logo

react-element-to-jsx-string's Introduction

react-element-to-jsx-string

Version Build Status License Downloads

Turn a ReactElement into the corresponding JSX string.

Useful for unit testing and any other need you may think of.

Features:

  • supports nesting and deep nesting like <div a={{b: {c: {d: <div />}}}} />
  • props: supports string, number, function (inlined as prop={function noRefCheck() {}}), object, ReactElement (inlined), regex, booleans (with or without shorthand syntax), ...
  • order props alphabetically
  • sort object keys in a deterministic order (o={{a: 1, b:2}} === o={{b:2, a:1}})
  • handle ref and key attributes, they are always on top of props
  • React's documentation indent style for JSX

Table of Contents generated with DocToc

Setup

yarn add react-element-to-jsx-string [--dev]

Usage

import React from 'react';
import reactElementToJSXString from 'react-element-to-jsx-string';

console.log(reactElementToJSXString(<div a="1" b="2">Hello, world!</div>));
// <div
//   a="1"
//   b="2"
// >
//   Hello, world!
// </div>

API

reactElementToJSXString(ReactElement[, options])

options.displayName: function(ReactElement)

Provide a different algorithm in charge of finding the right display name (name of the underlying Class) for your element.

Just return the name you want for the provided ReactElement, as a string.

options.filterProps: string[] | (val: any, key: string) => boolean, default []

If an array of strings is passed, filter out any prop who's name is in the array. For example ['key'] will suppress the key="" prop from being added.

If a function is passed, it will be called for each prop with two arguments, the prop value and key, and will filter out any that return false.

options.showDefaultProps: boolean, default true

If true, default props shown.

If false, default props are omitted unless they differ from from the default value.

options.showFunctions: boolean, default false

If true, functions bodies are shown.

If false, functions bodies are replaced with function noRefCheck() {}.

options.functionValue: function, default (fn) => fn

Allows you to override the default formatting of function values.

functionValue receives the original function reference as input and should send any value as output.

options.tabStop: number, default 2

Provide a different number of columns for indentation.

options.useBooleanShorthandSyntax: boolean, default true

If true, Boolean prop values will be omitted for shorthand syntax.

If false, Boolean prop values will be explicitly output like prop={true} and prop={false}

options.maxInlineAttributesLineLength: number, default undefined

Allows to render multiple attributes on the same line and control the behaviour.

You can provide the max number of characters to render inline with the tag name. If the number of characters on the line (including spacing and the tag name) exceeds this number, then all attributes will be rendered on a separate line. The default value of this option is undefined. If this option is undefined then if there is more than one attribute on an element, they will render on their own line. Note: Objects passed as attribute values are always rendered on multiple lines

options.sortProps: boolean, default true

Either to sort or not props. If you use this lib to make some isomorphic rendering you should set it to false, otherwise this would lead to react invalid checksums as the prop order is part of react isomorphic checksum algorithm.

options.useFragmentShortSyntax: boolean, default true

If true, fragment will be represented with the JSX short syntax <>...</> (when possible).

If false, fragment will always be represented with the JSX explicit syntax <React.Fragment>...</React.Fragment>.

According to the specs:

  • A keyed fragment will always use the explicit syntax: <React.Fragment key={...}>...</React.Fragment>
  • An empty fragment will always use the explicit syntax: <React.Fragment />

Note: to use fragment you must use React >= 16.2

Environment requirements

The environment you use to use react-element-to-jsx-string should have ES2015 support.

Use the Babel polyfill or any other method that will make you environment behave like an ES2015 environment.

Test

yarn test
yarn test:watch

Build

yarn build
yarn build:watch

Release

Decide if this is a patch, minor or major release, look at http://semver.org/

npm run release [major|minor|patch|x.x.x]

Thanks

alexlande/react-to-jsx was a good source of inspiration.

We built our own module because we had some needs like ordering props in alphabetical order.

react-element-to-jsx-string's People

Contributors

alexkirsz avatar andarist avatar armandabric avatar beauroberts avatar dependabot[bot] avatar giedrius-timinskis avatar goloroden avatar gpeal avatar greenkeeperio-bot avatar hhogg avatar kamal avatar lahmatiy avatar leoasis avatar markhughes avatar pascalduez avatar rarkins avatar redox avatar renovate-bot avatar renovate[bot] avatar samwalshnz avatar shouze avatar sinewyk avatar skvale avatar skycloud1030 avatar slightlytyler avatar smacker avatar tisoap avatar tiush avatar ttoohey avatar vvo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-element-to-jsx-string's Issues

npm `prepublish` depreciation

When releasing, npm output some warnings:

npm WARN prepublish-on-install As of npm@5, `prepublish` scripts are deprecated.
npm WARN prepublish-on-install Use `prepare` for build steps and `prepublishOnly` for upload-only.
npm WARN prepublish-on-install See the deprecation note in `npm help scripts` for more information.

Version update of 'stringify-update' dependency can break things

This recent commit bumped the version of stringify-object from 2.4.1 to 3.1.0.

stringify-object now publishes their code only in ES2015 syntax. This is a problem as react-element-to-jsx-string is a dependency of chai-enzyme which is often run in non-ES2015 environments (e.g. PhantomJS) with webpack.

People usually do not transpile their node_modules dependencies down to ES5 because they expect them to be published as ES5 already.

This possibly breaks a few builds and npm scripts around the world as people can't run npm test in their react apps anymore without fixing up their webpack config.

Possible error output:

PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR
  SyntaxError: Unexpected token 'const'
  at webpack:///~/stringify-object/index.js:2:0

Possible workaround is to manually run the affected modules through babel in your webpack config. Add another loader like this:

{
  test: /\.js$/,
  // transpile stringify-object and its dependency
  include: [/stringify-object|get-own-enumerable-property-symbols/],
  loader: 'babel-loader'
}

TLDR: Many react/webpack apps use chai-enzyme which has dependency on this project which has now a dependency on a ES2015 module which doesn't get automatically transpiled under most circumstances. This is a not a bug in this project but rather an inconvenience. What should we do?

Feature request: add an option to display plain object and array props without collapsing whitespace

Hey – love this utility! Use it all the time.

I've got some cases where certain props accept nested objects which can be difficult to read when they appear on a single line with whitespace removed. An example:

<Menu items={[{id: 'one', label: 'One'}, {id: 'two', label: 'Two'}, {id: 'three', label: 'Three'}]} />

It'd be great to pass an option like { collapseWhitespace: false } and see something like this instead:

<Menu
  items={[
    {
      id: 'one',
      label: 'One'
    },
    {
      id: 'two',
      label: 'Two'
    },
    {
      id: 'three',
      label: 'Three'
    }
  ]}
 />

Not sure if that's of interest to you or anyone else, but on the off chance that it is I'll submit a PR momentarily.

Parsing styled-jsx

Hi,

I'm working on our UI Library and I want to convert all the components to string so we can shown it as code ready to copy and paste.

We use styled-jsx and we need to convert snippets like this ⬇️ into strings.

<Button type="button" size="md" primary>Save</Button>
      <style jsx>{`
        .address{
          grid-template-columns: 66% 28%;
          display: grid;
          justify-content: space-between;
        }
`}</style>

This is the current output:

  <Button
    primary
    type="button"
  >
    Save
  </Button>
  <_class
    css=".address[data-jsx=&quot;2524236662&quot;]{-ms-grid-columns: 66% 28%;grid-template-columns: 66% 28%;display: -ms-grid;display: grid;-webkit-box-pack: justify;-ms-flex-pack: justify;justify-content: space-between;}
/*@ sourceURL=components/ui-library/Forms.js */
/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9yaWNhcmRvcmF1Y2gvU2l0ZXMvc2NhbGVhcGkuY29tL2Zyb250ZW5kL2NvbXBvbmVudHMvdWktbGlicmFyeS9Gb3Jtcy5qcyIsImNvbXBvbmVudHMvdWktbGlicmFyeS9Gb3Jtcy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUEwQ2tCLGdDQUV1QiwwQkFDakIsQUFEaUIsK0JBQ2pCLGtCQUNpQixBQURqQixjQUNpQiwwQkFDaEMsQUFEZ0MsdUJBQ2hDLEFBRGdDLCtCQUNoQyxDQUFBO0FDN0NULCtDQUErQyIsImZpbGUiOiJ0by5jc3MiLCJzb3VyY2VzQ29udGVu0= */"
    styleId={2524236662}
  />
</Form>

My code:

    let codeForm = reactElementToJSXString(
      this.props.children,
      {
        showDefaultProps: false,
        filterProps: ['data-jsx']
      }
    );

Thanks for this amazing lib!

Function as children display

Hi,

is react-element-to-jsx-string able to output/format a "Function as children"? (More infos)

const Foo = (props) => (
  <div>
    {props.children()}
  </div>
);

const Bar = () => (
  <Foo>{() => (
    <span>Yeah</span>
  )}</Foo>
);

Output from react-element-to-jsx-string:

<Foo />

Expected output:

<Foo>{() => (
  <span>Yeah</span>
)}</Foo>

Symbol to not generate a valid JSX string

const mySymbol = Symbol('foo');

console.log(reactElementToJsxString(<Button type={mySymbol} />));

It will output:

<Button type={Symbol(foo)} />

A valid JSX output could be:

<Button type={Symbol('foo')} />

See:

Support Symbol prop types

As a developer I want to use Symbols as prop types

Given I have a component <Button />
And I want to give that component a type "Primary"
And I use const TYPE_PRIMARY = Symbol('TYPE_PRIMARY') to specify a button type
And I have the following react element { ...otherAttributes, props: { type: TYPE_PRIMARY } }
And I pass through react-element-to-jsx-string

Then I expect the resulting jsx string to be <Button type={TYPE_PRIMARY} />

But I get an error "Uncaught TypeError: Cannot convert a Symbol value to a string"


I understand that we do not have the actual variable name that is used, and we can not be sure that the symbols name is mapping to that.

I'd propose to add a way to extend formatValue via options, so that I as user of this lib, can decide that on my own.

Spaces between words and inline elements are lost

If I start with this JSX:

<div>
  foo <strong>bar</strong> baz
</div>

That renders to React element that with children like this:

[ 
  'foo ',
  { type: 'strong', props: { children: [Object] }, .. },
  ' baz'
]

If I then pass that element through this module, I come out with this JSX — replacing some whitespaces with * to clarify:

<div>
  foo*
  <strong>
    bar
  </strong>
  *baz
</div>

The problem is that with the reformatting, those whitespace are actually lost. End-of-line and beginning-of-line whitespace is not meaningful, so the output HTML is actually this:

<div>
  foo<strong>bar</strong>baz
</div>

If introducing all the line breaks is the preference here, I think one fix would be to add spaces as strings, e.g.

<div>
  foo{' '}
  <strong>
    bar
  </strong>
  {' '}baz
</div>

Can't run on [email protected]

Hi I update my react-addons-test-utils to 15.4.0-rc.3, that the error occurs when I run npm test.

ERROR in .//react-element-to-jsx-string//react-addons-test-utils/index.js
Module not found: Error: Can't resolve 'react/lib/ReactTestUtils' in '/Users/Welly/Desktop/react-cool-starter/node_modules/react-element-to-jsx-string/node_modules/react-addons-test-utils'
@ .//react-element-to-jsx-string//react-addons-test-utils/index.js 1:17-52
@ .//react-element-to-jsx-string/index-dist.js
@ .//chai-enzyme/build/assertions/contain.js
@ ./~/chai-enzyme/build/index.js
@ ./tools/testing/test-bundler.js

Any solution for this?

API request: filterFunction

The filterProps option is helpful, but lacks the ability to dynamically filter props based on anything other than their name.

What if the API included a filterFunction option, that would take propNames and allow us to pass our own filter function body? That way we could also filter out props based on more dynamic criteria. E.g. the prop's value, or the props type.

For example:

reactElementToJSXString(element, {
  filterProps: ['onClick'], // useful in scenarios when you know the specific prop names
  filterFunction: propName => typeof element.props[propName] !== 'function' // don't render props which are functions
  // or
  filterFunction: propName => !element.props[propName] // don't render props that have falsy values (e.g. empty strings)
})

Thanks for your work on this library!

Support for IE11

This currently the latest version of stringify-object unfortunately it isn't published with an ES5 compiled version.
I opened an issue there to publish an ES5 compliant version.
In case this won't get approved, I'm willing to make a PR to make the required changes to support IE11 😃

Release 5.0.1 introduced breaking change compared to 5.0.0

In release 5.0.1 the dependency on stringify-object has been upgraded from ^2.3.1 to 3.0.0. This is a breaking change, as [email protected] dropped support for Node 0.12 and 0.13, now relying on basic ES6 features such as const. In fact, this also means that react-element-to-jsx-string does not work in PhantomJS anymore without explicitly transpiling its dependencies to ES5. This also affects chai-enzyme, for instance.

I would suggest making this kind of upgrade only within major version changes to avoid such problems. Do you think you could come up with a fix? Is [email protected] really required at the moment?

UglifyJS throw 'Invalid assignment' error

Hi,

Thanks for this awesome library!

I'm creating a component library using an nwb boilerplate (https://github.com/insin/nwb/blob/master/docs/guides/ReactComponents.md#developing-react-components-and-libraries-with-nwb).

Once I added react-element-to-jsx-string the build fails with the following error:

Failed to compile with 1 error.

 ERROR  in demo.1990f3e7.js from UglifyJs
Invalid assignment [./~/stringify-object/index.js:6,0][demo.1990f3e7.js:11007,34]

Is this an issue with stringify-object?

Boolean props with a default value of `true` are not rendered when the value is `false`

If you create a component with a default boolean prop set to true, like this:

class DefaultPropsComponent extends React.Component {}

DefaultPropsComponent.defaultProps = {test: 'test', something: true};

and then render an instance of that component where the prop is false:

reactElementToJSXString(<DefaultPropsComponent something={false} />, {showDefaultProps: false})
// Result: <DefaultPropsComponent />

the resulting string does not include something={false} as expected.

I'll submit a PR momentarily!

Babel helpers missing

Hi,

recent changes in #242 introduced the use of the babel-plugin-external-helpers.
This yet produce exceptions babelHelpers is not defined since it's expecting it on the global object.

I use the lib bundled with webpack

EDIT: There seem to be several issues actually. The esm build is still compiled to commonjs.

Scoped components output

Issue: <Card.Header /> renders to <CardHeader />

Is there a way to prevent this from happening?

Example usage:

import React from 'react'
import reactElementToJSXString from 'react-element-to-jsx-string'
import { Card } from 'example-module'

console.log(reactElementToJSXString((
  <Card>
    <Card.Header title='Sample Card' />
    <Card.Body>
      So long and thanks for all the fish.
    </Card.Body>
  </Card>
), { maxInlineAttributesLineLength: 80 })

// <Card>
//   <CardHeader title="Sample Card" />
//   <CardBody>
//     So long and thanks for all the fish.
//   </CardBody>
// </Card>

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on all branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because we are using your CI build statuses to figure out when to notify you about breaking changes.

Since we did not receive a CI status on the greenkeeper/initial branch, we assume that you still need to configure it.

If you have already set up a CI for this repository, you might need to check your configuration. Make sure it will run on all new branches. If you don’t want it to run on every branch, you can whitelist branches starting with greenkeeper/.

We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

Broken using React 0.14 and NPM 2

react-element-to-jsx-string lists React 0.15 as a dependency, which npm 2 will complain about if an application uses React 0.14.

FYI, I was pulling "jsx-chai": "^2.0.0" which in turn pulls react-element-to-jsx-string. npm 2 installs React 0.15 for you and then errors on invalid peer dependencies, because everything else in the application expects 0.14.

Props that differ from their defaults not rendered when showDefaultProps option is false

First, thanks for creating such a great utility! Now, onto the issue I've run into:

Taking a component used in the tests:

class DefaultPropsComponent extends React.Component {}

DefaultPropsComponent.defaultProps = {test: 'test'};

The following case correctly omits the prop from the JSX string:

reactElementToJSXString(<DefaultPropsComponent />, {showDefaultProps: false})
// <DefaultPropsComponent />

But if you change the prop's value from the default, it doesn't get rendered:

reactElementToJSXString(<DefaultPropsComponent test="foo" />, {showDefaultProps: false})
// <DefaultPropsComponent />

I would expect the result to be

// <DefaultPropsComponent test="foo" />

I'm just about to submit a pull request with a test and a fix.

On windows machines, get an error: Array.prototype.sort callback must be a function

On my mac, and on our linux CI server, using karma and phantom js 2.0 and this library, we do not get an error.

We have the requirement to deploy the code onto a windows pc. When running tests on that pc, using phantom 2.0 and windows 8.1, we get an error:

TypeError: Array.prototype.sort callback must be a function
at Array.sort (base/node_modules/es5-shim/es5-shim.min.js:6:10070)
at sortObject (base/src/test_helpers/requires/test_index.js:28145:36)
at stringifyObject (base/src/test_helpers/requires/test_index.js:7968:42)
at formatValue (base/src/test_helpers/requires/test_index.js:7945:58)
at formatJSXAttribute (base/src/test_helpers/requires/test_index.js:7929:19)
at getJSXAttribute (base/src/test_helpers/requires/test_index.js:7920:15)
at base/src/test_helpers/requires/test_index.js:7913:15
at Array.map (native)
at formatProps (base/src/test_helpers/requires/test_index.js:7912:58)
at toJSXString (base/src/test_helpers/requires/test_index.js:7852:18)
at base/src/test_helpers/requires/test_index.js:7956:15
at Array.map (native)
at toJSXString (base/src/test_helpers/requires/test_index.js:7893:63)
at reactElementToJSXString (base/src/test_helpers/requires/test_index.js:7833:11)
at Assertion.includeJSX (base/src/test_helpers/requires/test_index.js:7769:45)
at Assertion.assert (base/src/test_helpers/requires/test_index.js:3979:50)

sortobject update (1.1.0) breaks webpack

sortobject are updated to 1.1.0 today, and it uses editions to select correct build for consumer environment.

However, it seems webpack cannot work correctly with this, which throw an error "cannot find package.json".

Reproduce: npm install react-element-to-jsx-string. Make sure that it also installs [email protected]. Then use it like in Readme to see error.

Temporary Solution: Remove sortobject and reinstall [email protected]

Escape strings of HTML within <code> blocks

I have an element that looks like this:

{ 
  '$$typeof': Symbol(react.element),
  type: 'code',
  key: 'h-4',
  ref: null,
  props:
   { className: 'language-javascript',
     children: [ '<div style={{ color: pink }}>123459254321</div>\n' ] },
  _owner: null,
  _store: {} 
}

It's a <code> element with JSX inside of it.

The output from this module gives no special treatment to the JSX within the <code> element, so it ends up coming out as regular JSX: <code><div style=...></div></code>. Re-render that JSX and you have something different than what you started with.

I think this situation could be represented in JSX like <code>{'<div style=...'}</div>. You could also escape the < > signs, maybe.

I also think the same problem would apply to HTML within <code> blocks.

Do you think I'm misunderstanding something, or is this a bug?

Ability to configure how to show the component's display name

Some times you want to have control on how to display components' names. When you have components wrapped in a higher order component, sometimes it makes sense to just hide that when rendering the JSX and just show the original component's name (i.e. when rendering to a string that will be used as the markup example in a styleguide). This should not only be configurable for top level components, but also for all the components appearing as props in any level. I think probably providing a function that receives an element and returns the display name as part of some options to provide to the reactElementToJSXString function, would be the right API.

What do you think?

Add .babelrc to .npmignore file

Hi I am using your library and for some reason my webpack build process is picking up your .babelrc file making my builds fail because I don't have all the plugins and presets you use in your library. This shouldn't be happening because my code is not building your library (and the plugins/presets from your library are under devDependencies), your library is compiled before publishing to index-dist.js so I shouldn't need any of your build-process stuff. If I remove project_root/node_modules/react-element-to-jsx-string/.babelrc file the build works as normal.

So all we need to do to fix these problems is adding a .npmignore file in the repository:

.babelrc

And republish the project to NPM.

Also thanks for the lib, pretty neat.

Displaying template literals for code component

Hello!

I have this React component:

      <Code type="block">
{`var foo = 'bar';
var bat = 'baz';`}
      </Code>

The template literal is transpiled to ES5 and the props.children becomes a string like this:

var foo = 'bar';
var bat = 'baz';

When displaying this string in our documentation, it ends up looking like this:

screenshot 2016-07-18 17 49 57

This is a problem because copying and pasting the source code would not produce the desired multiline output.

It doesn't seem like there is any functionality that allows us to re-add the template literals. Is this something that this project would like to support or has any known workarounds?

If not, I suppose I could check to see if it is the code component and modify the children string to include the template literals.

Thanks for all the hard work! This is a great project and we're happily using for our documentation site.

Arrow functions are converted to traditional functions

Hi, I have the following component:

<Button onClick={e => console.log(e)}>Click me</Button>

But it is transformed to this instead:

<Button
  onClick={function onClick(e) {
                return console.log(e);
            }}
>
  Click me
</Button>

This cast is not only visually bad, it also changes the function behavior since an arrow function passes the this value from the context and not function. We might want to use "this" inside the callback function to alter the parent component state.

By the way, this library is very useful ! Thanks 👍

newlines on windows

Hi.

I suggest replacing the "\n" chars with a platform-dependent newline,
i.e. if on node var endOfLine = require('os').EOL;

As evident in the screenshot here from expect-jsx, the current way of formatting the output will be a problem to read for larger components. I guess the explicit '\n' chars are meant to be printed as newlines instead and this is a general bug occurring on windows machines?

Right now I just use .replace(/\\n/g, "\r\n").

If it's not a quick fix, let me know and I'll make a pull-request. ^_^

Cheers

Webpack / UglifyJS bundling process issue

Thanks for the utility, it is/was working great!

I am utilizing it in a custom addon for react-storybook. Until I upgraded react-storybook to their webpack 2 update it seemed to be working fine. But I am having an issue now with webpack/babel/uglify build of react-storybook processing this package. Digging into it this may not be an issue with react-element-to-jsx-string but really its stringify-object dependency.

yeoman/stringify-object#35

It seems that the compiled version was not intended for browser usages and it's compiled file is shipped containing arrow functions that will break within uglify since it won't process ES2015.

Is anyone else experiencing browser usage issues? I tried processing stringify-object with babel as part of the build but to no avail. Being that it is a dependency of a dependency I am not sure that the end user would be responsible or aware of how to use this properly...

Any ideas, suggestions, or solutions would be appreciated.

Thanks again!

Error: Expected a ReactElement, got `number`

Unit test:

import expect from 'expect';
import expectJSX from 'expect-jsx';
import React from 'react';

import { createRenderer } from 'react-addons-test-utils';

expect.extend(expectJSX);

describe(`toEqualJSX`, () => {
    it('should accept JSX with numbers', () => {
        const MyTable = () => (
            <span>{123}</span>
        )
        const shallowRenderer = createRenderer();
        shallowRenderer.render(<MyTable/>);
        const component = shallowRenderer.getRenderOutput();
        expect(component).toEqualJSX(<span>123</span>);
    });
});

Output:

  1) toEqualJSX should accept JSX with numbers:
     Error: react-element-to-jsx-string: Expected a ReactElement, got `number`
      at toJSXString (node_modules/expect-jsx/node_modules/react-element-to-jsx-string/index-dist.js:51:11)
      at node_modules/expect-jsx/node_modules/react-element-to-jsx-string/index-dist.js:179:12
      at Array.map (native)
      at toJSXString (node_modules/expect-jsx/node_modules/react-element-to-jsx-string/index-dist.js:104:97)
      at reactElementToJSXString (node_modules/expect-jsx/node_modules/react-element-to-jsx-string/index-dist.js:37:10)
      at Expectation.toEqualJSX (node_modules/expect-jsx/index-dist.js:27:78)
      at Context.<anonymous> (app/frontend/test/unit/components/Assessment/Test.spec.js:17:27)

I managed to fix it by adding another condition on type 'number' on

if (typeof ReactElement === 'string') {

Edge case with empty elements

I am using tape-jsx-equals and have the following code

  renderer.render(
    <Picture />
  )
  t.jsxEquals(
    renderer.getRenderOutput(),
    <div></div>,
    "should render nothing if nothing is passed as props"
  )

(I only pasted the relevant part of my code)

The issue I get is:

    expected: '<div />'
    actual:   '<div>\n  \n</div>'

The expected result I wrote is <div></div>, but somehow it got transformed to <div />. Maybe by babel.

Maybe <div>{whitespace}</div> should be rendered to <div />?

Quite a bit confused about the api. How would I pass in a custom component and get its jsx rendered?

Hi there, I'm having trouble understanding your api. What I'm hoping to achieve is import a custom react component, either class based or stateless functional, and pass it into the reactElementToJSXString() method. So far all I get when I pass in the component is the name of the component but not the JSX inside of it. Clearly I'm failing to grasp something here.

Lets say I wanted to import the custom component.
import CustomComponent from './CustomComponent'

Then at some point, I'd call the method and pass the component in reactElementToJSXString(<CustomComponent />)

What I get back is just a string of <CustomComponent /> rather than something like <div>Sup</div>

Would appreciate any insight you can provide.

"Warning: Accessing PropTypes via the main React package is deprecated" for React 15.5+

With commit 73d6052 some import were changed to:

import * as React from 'react';

In this case babel uses _interopRequireWildcard which is using for..in to make a copy of module exports. This cause to warning when React 15.5+ is using:

Warning: Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead.

Because with React 15.5, importing PropTypes from React is deprecated in favour of importing from the new 'prop-types' package.

Don't fetch value from constant

Example:

// Button.js
export const PRIMARY = Symbol();

export default const Button = (props, children) => {
  switch (props.type) {
    case PRIMARY:
      theme = 'Button--primary';
      break;
  }
  return (<button className={ theme } { ...props }>{ children }</button>)
}
export default Button;
// view code-block
import jsxToString from 'react-element-to-jsx-string';
import Button, {  PRIMARY } from 'Button.js';

console.log(jsxToString(<Button type={PRIMARY}>Primary</Button>))

My Problem is that the constant is not PRIMARY but Symbol():

<Button type={Symbol()}>
  Primary
</Button>

Is there a way to workaround that?

Allow custom serialisation of prop values

Prop values of type Set are serialised as foo={[object Set]}. It would be much more convenient to serialised them in a similar way to the Arrays (i.e. foo={Set ['one', 'two', 'three']}).
This could be coded as an extension if custom serialisation of props were supported or as a specific prop serialiser for Set values.

Thanks,
Alberto

Linting errors when globally installed eslint is out of date

Hi! Thanks for an awesome tool!

I noticed a bunch of linting errors were popping up in my IDE, and it turns out that it's because I had a super old version of eslint globally installed. I was able to sort these out by installing the eslint and eslint-plugin-react packages as devDependencies.

I'll submit a tiny pull request in case it's useful.

React elements nested in array/object props contain unnecessary string escaping

Hi - thanks for an awesome tool!

I think this might be a regression but I'm not sure when it would have been introduced. I'm having issues with unnecessary string escaping on props that contain React elements with single quotes (e.g. <div object={{ nested: <div array={['hello', 'you']} /> }} />

I'll submit a pull request with a failing test but unfortunately I'm not able to investigate a fix right now. If no one else can look into it, I might get around to it in a few days:

+ expected - actual

  <div
    obj={{
-     nested: <div arr={[\'hello\', \'you\']} />
+     nested: <div arr={['hello', 'you']} />
    }}
   />

Array.prototype.fill

Array.prototype.fill polyfill is not standard implemented everywhere yet.

'undefined' is not a function (evaluating 'new Array(times).fill('  ')')

Make a note about it in the README ?

EventPluginRegistry: Cannot inject event plugin ordering more than once.

trying to install all at latest version:

   "react": "15.3.1",
   "react-native": "0.32.0",

I got first errors about missing modules:

    "babel-preset-es2015": "^6.14.0",
    "babel-preset-react": "^6.11.1",
    "babel-preset-stage-2": "^6.13.0",

On the import of the module:

 EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React.

anything I'm missing?

don't publish .babelrc

I get an error when I build my project with webpack because it says it can't find the babel plugin stage-2 which is specified in react-element-to-jsx-string's .babelrc. It is my understanding that this file shouldn't be published to npm at all since it's only used to build the ES6 code which is then published. I depend on chai-enzyme which depends on this, and this ends up breaking my webpack build.

Searching around I found this which seems to resolve it by being specific about which files are published to the npm registry, by specifying something like "files": "./index-dist.js".

This way the .babelrc won't end up on the user's system, so babel won't attempt to obey it. I had to remove the .babelrc file myself from node_modules/react-element-to-jsx-string/.babelrc to resolve this.

Don't mess json & jsx syntaxes - don't escape json in formatTreeNode

In formatTreeNode() we escape strings & numbers without going further in the kind of what the string represents. We recently had the case of a ld+json string being inside a script tag:

<script type="application/ld+json">
{
    "@context": "http://schema.org",
    "@type": "Hotel",
    "name": "Le Figuier",
    "description": "L’Hôtel Le Figuier est un petit établissement confortable et familial, au coeur d’Ivry-sur-Seine, à seulement 2km de Paris.",
    "address": "72 Boulevard de Brandebourg, 94200 Ivry-sur-Seine, France",
    "telephone": "+33 1 46 72 72 72",
    "photo": "https://res.cloudinary.com/karibbu/image/upload/c_scale,w_1800/v1501161224/lefiguier94.fr/VLWPuJuF7uUKLwMKZTytxg.jpg",
    "image": "https://res.cloudinary.com/karibbu/image/upload/s--P27nN2Ub--/v1501162649/lefiguier94.fr/Logo-lefiguier-light-bkg.svg",
    "starRating": {
        "@type": "Rating",
        "ratingValue": 0
    }
}
</script>

Yes it's a string, but it's a pure json string, encapsulated into script tags. So ATM the behavior escape it so it's rendered like that:

<script type="application/ld+json">
&lbrace;
    "@context": "http://schema.org",
    "@type": "Hotel",
    "name": "Le Figuier",
    "description": "L’Hôtel Le Figuier est un petit établissement confortable et familial, au coeur d’Ivry-sur-Seine, à seulement 2km de Paris.",
    "address": "72 Boulevard de Brandebourg, 94200 Ivry-sur-Seine, France",
    "telephone": "+33 1 46 72 72 72",
    "photo": "https://res.cloudinary.com/karibbu/image/upload/c_scale,w_1800/v1501161224/lefiguier94.fr/VLWPuJuF7uUKLwMKZTytxg.jpg",
    "image": "https://res.cloudinary.com/karibbu/image/upload/s--P27nN2Ub--/v1501162649/lefiguier94.fr/Logo-lefiguier-light-bkg.svg",
    "starRating": &lbrace;
        "@type": "Rating",
        "ratingValue": 0
    &rbrace;
&rbrace;
</script>

And we expect to not having braces escaped. So the idea would be to make some extra assertions in formatTreeNode, something like that:

/* @flow */

import formatReactElementNode from './formatReactElementNode';
import type { Options } from './../options';
import type { TreeNode } from './../tree';

const escape = (s: string): string =>
  s.replace(/{/g, '&lbrace;').replace(/}/g, '&rbrace;');

export default (
  node: TreeNode,
  inline: boolean,
  lvl: number,
  options: Options
): string => {
  if (node.type === 'number') {
    return node.value.toString();
  }

  if (node.type === 'string') {
    try {
      const json = JSON.parse(node.value);
      return JSON.stringify(json);
    } catch (error) {
      return escape(node.value.toString();
    }
  }

  if (node.type === 'ReactElement') {
    return formatReactElementNode(node, inline, lvl, options);
  }

  throw new TypeError(`Unknow format type "${node.type}"`);
};

Update the changelog

There is no mention of the v5.0.0 in the changelog. Could you update it with the last change?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.