aboutsummaryrefslogtreecommitdiffstats
path: root/stories/react/utils/jsxToString.js
blob: 8b799ada4f0cb4bd848cc2fa8cba882a929a6f10 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import React, {Children} from 'react';

const INDENT = '   ';

function stringRepresentationForJsx(item) {
	if (typeof item === 'string') {
		return `'${item}'`;
	} else if (typeof item === 'number') {
		return item.toString();
	} else if (Array.isArray(item)) {
		return `[${item.map(val => stringRepresentationForJsx(val)).toString()}]`;
	}
	else if (typeof item === 'boolean') {
		return item.toString();
	}
	else if (typeof item === 'function') {
		return item.toString().replace(/\s{2,}/g, ' ');
	} else if (typeof item === 'object') {
		let repr = '{';
		for (let key in item) {
			if (item.hasOwnProperty(key)) {
				repr += `${key}: ${stringRepresentationForJsx(item[key])}, `;
			}
		}
		repr = repr.slice(0, -2);
		repr += '}';
		return repr;
	}
}

function parseProps(jsx, indentCount) {
	let result = '';
	for (let prop in jsx.props) {
		let value = jsx.props[prop];
		if (prop !== 'children' && value) {
			let repr = stringRepresentationForJsx(value);
			let isString = repr.startsWith("'");
			result += `\n${INDENT.repeat(indentCount)}${prop}`;
			if (value !== true) {
				result += `=${isString ? '' : '{ '}${stringRepresentationForJsx(value)}${isString ? '' : ' }'}`;
			}
		}
	}
	return result;
}

function jsxToString({jsx, indentCount=0, exclude}) {
	if (typeof jsx === 'string'){
		return jsx;
	}
	
	let name = typeof jsx.type === 'string' ? jsx.type : jsx.type.name;	
	let result = name === exclude ? ''
		: `${INDENT.repeat(indentCount)}<${name}${parseProps(jsx, indentCount + 1)}`;

	if (jsx.props.hasOwnProperty('children')) {
		let {children} = jsx.props;
		let childrenArr = Children.toArray(children);
		if (name !== exclude) { result += '>\n';}
		if (typeof children === 'string') {
			result += `${INDENT.repeat(indentCount + 1)}${children}\n`;
		} else {
			let newIndentCount = name === exclude ? indentCount : indentCount + 1;
			childrenArr.forEach(child => result += `${jsxToString({jsx: child, indentCount: newIndentCount})}\n`);
		}
		const closingTag = name === exclude ? '' 
			: `${INDENT.repeat(indentCount)}</${name}>`;
		return result + closingTag;
	}

	return result + ' />';
}

export default jsxToString;