"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _widestLine = _interopRequireDefault(require("widest-line")); var _wrapText = _interopRequireDefault(require("./wrap-text")); var _getMaxWidth = _interopRequireDefault(require("./get-max-width")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const isAllTextNodes = node => { if (node.nodeName === '#text') { return true; } if (node.nodeName === 'SPAN') { if (node.textContent) { return true; } if (Array.isArray(node.childNodes)) { return node.childNodes.every(isAllTextNodes); } } return false; }; // Squashing text nodes allows to combine multiple text nodes into one and write // to `Output` instance only once. For example, hello{' '}world // is actually 3 text nodes, which would result 3 writes to `Output`. // // Also, this is necessary for libraries like ink-link (https://github.com/sindresorhus/ink-link), // which need to wrap all children at once, instead of wrapping 3 text nodes separately. const squashTextNodes = node => { let text = ''; for (const childNode of node.childNodes) { let nodeText; if (childNode.nodeName === '#text') { nodeText = childNode.nodeValue; } if (childNode.nodeName === 'SPAN') { nodeText = childNode.textContent || squashTextNodes(childNode); } // Since these text nodes are being concatenated, `Output` instance won't be able to // apply children transform, so we have to do it manually here for each text node if (childNode.unstable__transformChildren) { nodeText = childNode.unstable__transformChildren(nodeText); } text += nodeText; } return text; }; // After nodes are laid out, render each to output object, which later gets rendered to terminal const renderNodeToOutput = (node, output, { offsetX = 0, offsetY = 0, transformers = [], skipStaticElements }) => { if (node.unstable__static && skipStaticElements) { return; } const { yogaNode } = node; // Left and top positions in Yoga are relative to their parent node const x = offsetX + yogaNode.getComputedLeft(); const y = offsetY + yogaNode.getComputedTop(); // Transformers are functions that transform final text output of each component // See Output class for logic that applies transformers let newTransformers = transformers; if (node.unstable__transformChildren) { newTransformers = [node.unstable__transformChildren, ...transformers]; } // Nodes with only text inside if (node.textContent) { let text = node.textContent; // Since text nodes are always wrapped in an additional node, parent node // is where we should look for attributes if (node.parentNode.style.textWrap) { const currentWidth = (0, _widestLine.default)(text); const maxWidth = (0, _getMaxWidth.default)(node.parentNode.yogaNode); if (currentWidth > maxWidth) { text = (0, _wrapText.default)(text, maxWidth, { textWrap: node.parentNode.style.textWrap }); } } output.write(x, y, text, { transformers: newTransformers }); return; } // Text nodes if (node.nodeName === '#text') { output.write(x, y, node.nodeValue, { transformers: newTransformers }); return; } // Nodes that have other nodes as children if (Array.isArray(node.childNodes) && node.childNodes.length > 0) { const isFlexDirectionRow = node.style.flexDirection === 'row'; if (isFlexDirectionRow && node.childNodes.every(isAllTextNodes)) { let text = squashTextNodes(node); if (node.style.textWrap) { const currentWidth = (0, _widestLine.default)(text); const maxWidth = (0, _getMaxWidth.default)(yogaNode); if (currentWidth > maxWidth) { text = (0, _wrapText.default)(text, maxWidth, { textWrap: node.style.textWrap }); } } output.write(x, y, text, { transformers: newTransformers }); return; } for (const childNode of node.childNodes) { renderNodeToOutput(childNode, output, { offsetX: x, offsetY: y, transformers: newTransformers, skipStaticElements }); } } }; var _default = renderNodeToOutput; exports.default = _default;