├── .gitignore
├── package.json
├── LICENSE
├── README.md
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-to-jsx",
3 | "version": "1.3.2",
4 | "main": "index.js",
5 | "author": "Alex Lande",
6 | "license": "MIT",
7 | "dependencies": {
8 | "jstoxml": "^0.2.3",
9 | "lodash": "^3.2.0",
10 | "react": "^0.13.3"
11 | },
12 | "description": "Generates a JSX string representation of React elements",
13 | "keywords": [
14 | "react",
15 | "jsx",
16 | "style-guide"
17 | ],
18 | "repository": {
19 | "type": "git",
20 | "url": "https://github.com/alexlande/react-to-jsx"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Alex Lande
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | **Important: `react-to-jsx` is deprecated and unmaintained. Use [react-element-to-jsx-string](https://github.com/algolia/react-element-to-jsx-string) instead!**
2 |
3 | # React to JSX
4 |
5 | Generates a JSX string representation of React elements. Takes a React Element (or an array of React Elements). Useful for generating React component style guides.
6 |
7 | ## Usage
8 |
9 | ### Install
10 |
11 | ```
12 | npm install react-to-jsx
13 | ```
14 |
15 | ### Basic Usage
16 |
17 | ```js
18 | var reactToJsx = require('react-to-jsx');
19 |
20 | var jsxString = reactToJsx(
21 |
26 | );
27 |
28 | //
33 |
34 | console.log(jsxString);
35 | ```
36 |
37 | ### Options
38 |
39 | `reactToJsx` takes an optional `options` object: `reactToJsx(reactElement, options)`.
40 |
41 | #### `indent`
42 |
43 | Type: `String` Default: `'\t'` (Tab)
44 |
45 | Sets the indent string for returned JSX. Should probably match your preferred
46 | code style. Two spaces? Four? Three? The choice is yours, friend.
47 |
48 | #### `includeNull`
49 |
50 | Type: 'Boolean' Default: `true`
51 |
52 | Determines whether to include props with a value of `null` in the returned JSX.
53 |
54 | #### `exclude`
55 |
56 | Type: `Array` Default: `[]`
57 |
58 | Array of props to exclude from the returned JSX. Hide those weird props, they shouldn't be in your docs anyway.
59 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 | var jstoxml = require('jstoxml');
3 | var React = require('react');
4 |
5 | var componentToJson = function (component, config) {
6 | var componentJson = {};
7 | var componentArray = [];
8 | var name;
9 |
10 | if (_.isArray(component)) {
11 | _.forEach(component, function (item) {
12 | componentArray.push(componentToJson(item, config));
13 | });
14 |
15 | return componentArray;
16 | }
17 |
18 | if (component.type && (component.type.displayName || component.type.name)) {
19 | name = component.type.displayName || component.type.name;
20 | } else if (component.type) {
21 | name = component.type;
22 | } else {
23 | return component;
24 | }
25 |
26 | var children;
27 |
28 | if (component.props && component.props.children) {
29 | children = component.props.children;
30 | children = _.isArray(children) ? children : [children];
31 | children = _.map(children, function (child, config) {
32 | return componentToJson(child, config);
33 | });
34 | }
35 |
36 | var matchingProps;
37 |
38 | if (component.type && component.type.defaultProps) {
39 | matchingProps = _.omit(component.props, function (val, key) {
40 | return component.type.defaultProps[key] === component.props[key];
41 | });
42 | } else {
43 | matchingProps = component.props;
44 | }
45 |
46 | var props = _.chain(matchingProps)
47 | .omit(['children'])
48 | .transform(function (result, prop, key) {
49 | if (_.isUndefined(prop)) {
50 | return;
51 | } else if (_.isNull(prop) && !config.includeNull) {
52 | return;
53 | } else if (config.exclude && config.exclude.indexOf(key) !== -1) {
54 | return;
55 | } else if (_.isString(prop)) {
56 | result[key] = prop;
57 | } else if (_.isFunction(prop)) {
58 | result[key] = 'LITERAL!function!LITERAL';
59 | } else if (React.isValidElement(prop)) {
60 | result[key] = 'LITERAL!ReactElement!LITERAL';
61 | } else {
62 | var stringified;
63 |
64 | try {
65 | stringified = JSON.stringify(prop);
66 | } catch(e) {
67 | stringified = '[Circular JSON]';
68 | }
69 |
70 | result[key] = 'LITERAL!' + stringified + '!LITERAL';
71 | }
72 | })
73 | .value();
74 |
75 | componentJson = {
76 | _name: name,
77 | _attrs: props,
78 | _content: children
79 | };
80 |
81 | return componentJson;
82 | }
83 |
84 | var reactToJsx = function (component, options) {
85 | var defaults = {
86 | indent: '\t',
87 | includeNull: true,
88 | exclude: []
89 | };
90 |
91 | var config = _.extend({}, defaults, options);
92 |
93 | var componentXml = jstoxml.toXML(componentToJson(component, config), {
94 | indent: config.indent
95 | });
96 |
97 | componentXml = componentXml
98 | .replace(/"LITERAL!/g, '{')
99 | .replace(/!LITERAL"/g, '}')
100 |
101 | var componentArray = componentXml.split('\n');
102 |
103 | componentArray = _.map(componentArray, function (line) {
104 | var attributeMatcher = /\s+(?=\S*=)/g;
105 |
106 | if ((line.match(attributeMatcher) || []).length < 2) {
107 | return line;
108 | }
109 |
110 | var indentRegex = new RegExp(config.indent, 'g');
111 |
112 | var indentDepth = (line.match(indentRegex) || []).length;
113 | var newlineString = '\n' + config.indent;
114 |
115 | for (var i = 0; i < indentDepth; i++) {
116 | newlineString += config.indent;
117 | }
118 |
119 | line = line.replace(attributeMatcher, newlineString);
120 |
121 | return line;
122 | });
123 |
124 | componentXml = componentArray.join('\n');
125 |
126 | return componentXml;
127 | };
128 |
129 | module.exports = reactToJsx;
130 |
--------------------------------------------------------------------------------