| function addPath(node, parentPath) { |
| if (!parentPath) { |
| return node; |
| } |
| return { ...node, file: parentPath + '/' + node.file }; |
| } |
| |
| function flatten(nodes, parentPath) { |
| let children = []; |
| for (let i = 0; i < nodes.length; i++) { |
| const child = nodes[i]; |
| if (child.children) { |
| children = [ |
| ...children, |
| ...flatten( |
| child.children, |
| (parentPath ? parentPath + '/' : '') + child.file |
| ) |
| ]; |
| } else { |
| children.push(addPath(child, parentPath)); |
| } |
| } |
| return children; |
| } |
| |
| function filterByFile(nodes, fileFilter, parentPath) { |
| let children = []; |
| |
| for (let i = 0; i < nodes.length; i++) { |
| const child = nodes[i]; |
| const childFullPath = (parentPath ? parentPath + '/' : '') + child.file; |
| |
| const isChildUnderFilter = |
| fileFilter === childFullPath || |
| fileFilter.indexOf(childFullPath + '/') === 0; |
| const isChildAboveFilter = |
| childFullPath.indexOf(fileFilter + '/') === 0; |
| |
| if (isChildUnderFilter) { |
| // flatten and continue looking underneath |
| children = [ |
| ...children, |
| ...filterByFile(child.children, fileFilter, childFullPath) |
| ]; |
| } else if (isChildAboveFilter) { |
| // remove the parent path and add everything underneath |
| const charsToRemoveFromFile = |
| fileFilter.length - (parentPath ? parentPath.length : 0); |
| let childFilename = child.file.slice(charsToRemoveFromFile); |
| if (childFilename[0] === '/') { |
| childFilename = childFilename.slice(1); |
| } |
| children.push({ |
| ...child, |
| file: childFilename |
| }); |
| } |
| } |
| return children; |
| } |
| |
| function sort(childData, activeSort) { |
| const top = activeSort.order === 'asc' ? 1 : -1; |
| const bottom = activeSort.order === 'asc' ? -1 : 1; |
| childData.sort((a, b) => { |
| let valueA; |
| let valueB; |
| if (activeSort.sortKey === 'file') { |
| valueA = a.file; |
| valueB = b.file; |
| } else { |
| const [metricType, valueType] = activeSort.sortKey.split('.'); |
| valueA = a.metrics[metricType][valueType]; |
| valueB = b.metrics[metricType][valueType]; |
| } |
| |
| if (valueA === valueB) { |
| return 0; |
| } |
| return valueA < valueB ? top : bottom; |
| }); |
| |
| for (let i = 0; i < childData.length; i++) { |
| const child = childData[i]; |
| if (child.children) { |
| childData[i] = { |
| ...child, |
| children: sort(child.children, activeSort) |
| }; |
| } |
| } |
| return childData; |
| } |
| |
| function filter(nodes, metricsMap, activeFilters) { |
| const children = []; |
| for (let i = 0; i < nodes.length; i++) { |
| let child = nodes[i]; |
| if (child.children) { |
| const newSubChildren = filter( |
| child.children, |
| metricsMap, |
| activeFilters |
| ); |
| if (newSubChildren.length) { |
| child = { ...child, children: newSubChildren }; |
| children.push(child); |
| } |
| } else { |
| if ( |
| (metricsMap.statements && |
| activeFilters[child.metrics.statements.classForPercent]) || |
| (metricsMap.branches && |
| activeFilters[child.metrics.branches.classForPercent]) || |
| (metricsMap.functions && |
| activeFilters[child.metrics.functions.classForPercent]) || |
| (metricsMap.lines && |
| activeFilters[child.metrics.lines.classForPercent]) |
| ) { |
| children.push(child); |
| } |
| } |
| } |
| return children; |
| } |
| |
| module.exports = function getChildData( |
| sourceData, |
| metricsToShow, |
| activeSort, |
| isFlat, |
| activeFilters, |
| fileFilter |
| ) { |
| let childData = sourceData.children; |
| |
| if (isFlat) { |
| childData = flatten(childData.slice(0)); |
| } |
| |
| if (fileFilter) { |
| childData = filterByFile(childData, fileFilter); |
| } |
| |
| if (activeFilters.low) { |
| activeFilters = { ...activeFilters, empty: true }; |
| } |
| childData = filter(childData, metricsToShow, activeFilters); |
| |
| if (activeSort) { |
| childData = sort(childData, activeSort); |
| } |
| return childData; |
| }; |