-
-
Notifications
You must be signed in to change notification settings - Fork 628
/
Copy pathrenderer.js
96 lines (75 loc) · 2.6 KB
/
renderer.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
import Yoga from 'yoga-layout-prebuilt';
import Output from './output';
import {createNode, appendStaticNode} from './dom';
import buildLayout from './build-layout';
import renderNodeToOutput from './render-node-to-output';
// Since <Static> components can be placed anywhere in the tree, this helper finds and returns them
const getStaticNodes = element => {
const staticNodes = [];
for (const childNode of element.childNodes) {
if (childNode.unstable__static) {
staticNodes.push(childNode);
}
if (Array.isArray(childNode.childNodes) && childNode.childNodes.length > 0) {
staticNodes.push(...getStaticNodes(childNode));
}
}
return staticNodes;
};
// Build layout, apply styles, build text output of all nodes and return it
export default ({terminalWidth}) => {
const config = Yoga.Config.create();
// Used to free up memory used by last Yoga node tree
let lastYogaNode;
let lastStaticYogaNode;
return node => {
if (lastYogaNode) {
lastYogaNode.freeRecursive();
}
if (lastStaticYogaNode) {
lastStaticYogaNode.freeRecursive();
}
const staticElements = getStaticNodes(node);
if (staticElements.length > 1) {
if (process.env.NODE_ENV !== 'production') {
console.error('Warning: There can only be one <Static> component');
}
}
// <Static> component must be built and rendered separately, so that the layout of the other output is unaffected
let staticOutput;
if (staticElements.length === 1) {
const rootNode = createNode('root');
appendStaticNode(rootNode, staticElements[0], {woot: true});
const {yogaNode: staticYogaNode} = buildLayout(rootNode, {
config,
terminalWidth,
skipStaticElements: false
});
staticYogaNode.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_LTR);
// Save current Yoga node tree to free up memory later
lastStaticYogaNode = staticYogaNode;
staticOutput = new Output({
width: staticYogaNode.getComputedWidth(),
height: staticYogaNode.getComputedHeight()
});
renderNodeToOutput(rootNode, staticOutput, {skipStaticElements: false});
}
const {yogaNode} = buildLayout(node, {
config,
terminalWidth,
skipStaticElements: true
});
yogaNode.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_LTR);
// Save current node tree to free up memory later
lastYogaNode = yogaNode;
const output = new Output({
width: yogaNode.getComputedWidth(),
height: yogaNode.getComputedHeight()
});
renderNodeToOutput(node, output, {skipStaticElements: true});
return {
output: output.get(),
staticOutput: staticOutput ? `${staticOutput.get()}\n` : undefined
};
};
};