| 78 | |
| 79 | // Recursively build a tree from the list of allItems |
| 80 | function buildNestedToc(allItems, startIndex = 0) { |
| 81 | const startItem = allItems[startIndex] |
| 82 | if (!startItem) { |
| 83 | return [] |
| 84 | } |
| 85 | let curLevelIndentation = startItem.indentationLevel |
| 86 | const currentLevel = [] |
| 87 | |
| 88 | for (let cursor = startIndex; cursor < allItems.length; cursor++) { |
| 89 | const cursorItem = allItems[cursor] |
| 90 | const nextItem = allItems[cursor + 1] |
| 91 | const nextItemIsNested = nextItem && nextItem.indentationLevel > cursorItem.indentationLevel |
| 92 | |
| 93 | // if it's the current indentation level, push it on and keep going |
| 94 | if (curLevelIndentation === cursorItem.indentationLevel) { |
| 95 | currentLevel.push({ |
| 96 | ...cursorItem, |
| 97 | items: nextItemIsNested ? buildNestedToc(allItems, cursor + 1) : [], |
| 98 | }) |
| 99 | continue |
| 100 | } |
| 101 | |
| 102 | // these items were already handled via recursion |
| 103 | if (curLevelIndentation < cursorItem.indentationLevel) { |
| 104 | continue |
| 105 | } |
| 106 | |
| 107 | // current root indentation is _greater_ than our current cursor item, |
| 108 | if (curLevelIndentation > cursorItem.indentationLevel) { |
| 109 | // special scenario where the initial list started with "less important" headers |
| 110 | // so we need to reset our expectations of what level to judge the indentation on |
| 111 | if (startIndex === 0) { |
| 112 | curLevelIndentation = cursorItem.indentationLevel |
| 113 | currentLevel.push({ |
| 114 | ...cursorItem, |
| 115 | items: nextItemIsNested ? buildNestedToc(allItems, cursor + 1) : [], |
| 116 | }) |
| 117 | continue |
| 118 | } |
| 119 | break |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | return currentLevel |
| 124 | } |
| 125 | |
| 126 | // Strip the bits and pieces from each object in the array that are |
| 127 | // not needed in the React component rendering. |