/
to-jsx-string.js
104 lines (84 loc) · 2.37 KB
/
to-jsx-string.js
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import sobj from 'stringify-object';
function improveCurly(str) {
if (str.startsWith('{')) {
str = '{ ' + str.slice(1);
}
if (str.endsWith('}')) {
str = str.slice(0, -1) + ' }';
}
return str;
}
function getLevelIndentation(level) {
return new Array(level).fill(0).reduce((memo, _) => memo + ' ', '');
}
function getType(element) {
const { type } = element;
if ( ! type) {
return '';
}
return typeof type === 'string' ? type : type.name;
}
function renderStringProp(prop) {
const [ key, value ] = prop;
return `${key}="${value}"`;
}
function renderObjectProp(prop) {
const [ key, value ] = prop;
if (value === true) {
return key;
}
console.log(value);
const valueStr = improveCurly(sobj(value, { indent: ' ', inlineCharacterLimit: 50 }));
return `${key}={${valueStr}}`;
}
function renderProps(props) {
const { children, ...rest } = props;
return ' ' + Object.entries(rest)
.map((e) => typeof e[1] === 'string' ? renderStringProp(e) : renderObjectProp(e))
.join(' ');
}
function renderWithChildren(element, level) {
const { props } = element;
const children = Array.isArray(props.children) ? props.children : [ props.children ];
const type = getType(element);
const indentation = getLevelIndentation(level);
return [
`${indentation}<${type}${renderProps(props)}>`,
...children.reduce((memo, c) => [ ...memo, ...renderNode(c, level + 1) ], []),
`${indentation}</${type}>`,
];
}
function renderWithoutChildren(element, level) {
const { props } = element;
const type = getType(element);
const indentation = getLevelIndentation(level);
if ( ! type) {
return [
`${indentation}${element}`,
];
}
return [
`${indentation}<${type}${renderProps(props)} />`,
];
}
function renderNode(element, level) {
const { props } = element;
if (props && props.children) {
return renderWithChildren(element, level);
}
else {
return renderWithoutChildren(element, level);
}
}
export default function toJsxString(element) {
const code = renderNode(element, 0).map((l, i, a) => i != a.length - 1 ? l + '\n' : l).join('');
return code;
return window.prettier.format(code, {
semi: false,
jsxBracketSameLine: true,
singleQuote: true,
trailingComma: 'all',
arrowParens: 'always',
parser: window.prettierPlugins.babylon.parsers.babylon.parse,
}).slice(1).trim();
}