diff --git a/desktop/app/src/ui/components/elements-inspector/elements.tsx b/desktop/app/src/ui/components/elements-inspector/elements.tsx index 3c3da983e..72d2e36c2 100644 --- a/desktop/app/src/ui/components/elements-inspector/elements.tsx +++ b/desktop/app/src/ui/components/elements-inspector/elements.tsx @@ -221,6 +221,7 @@ type ElementsRowProps = { | ((key: ElementID | undefined | null) => void) | undefined | null; + onCopyExpandedTree: (key: Element, maxDepth: number) => string; style?: Object; contextMenuExtensions: Array; decorateRow?: DecorateRow; @@ -249,13 +250,14 @@ class ElementsRow extends PureComponent { { label: 'Copy', click: () => { - const attrs = props.element.attributes.reduce( - (acc, val) => acc + ` ${val.name}=${val.value}`, - '', - ); - clipboard.writeText(`${props.element.name}${attrs}`); + clipboard.writeText(props.onCopyExpandedTree(props.element, 0)); }, }, + { + label: 'Copy expanded child elements', + click: () => + clipboard.writeText(props.onCopyExpandedTree(props.element, 255)), + }, { label: props.element.expanded ? 'Collapse' : 'Expand', click: () => { @@ -637,6 +639,7 @@ export class Elements extends PureComponent { searchResults, contextMenuExtensions, decorateRow, + elements, } = this.props; const {flatElements} = this.state; @@ -654,6 +657,30 @@ export class Elements extends PureComponent { if (this.props.alternateRowColor) { isEven = index % 2 === 0; } + const onCopyExpandedTree = ( + maxDepth: number, + element: Element, + depth: number, + ): string => { + const shouldIncludeChildren = element.expanded && depth < maxDepth; + const children = shouldIncludeChildren + ? element.children.map((childId) => { + const childElement = elements[childId]; + return childElement == null + ? '' + : onCopyExpandedTree(maxDepth, childElement, depth + 1); + }) + : []; + + const childrenValue = children.toString().replace(',', ''); + const indentation = depth === 0 ? '' : '\n'.padEnd(depth * 2 + 1, ' '); + const attrs = element.attributes.reduce( + (acc, val) => acc + ` ${val.name}=${val.value}`, + '', + ); + + return `${indentation}${element.name}${attrs}${childrenValue}`; + }; return ( { onElementHovered && onElementHovered(key); }} onElementSelected={onElementSelected} + onCopyExpandedTree={(element, maxDepth) => + onCopyExpandedTree(maxDepth, element, 0) + } selected={selected === row.key} focused={focused === row.key} matchingSearchQuery={