@mishasinitcyn/betterrank 0.2.10 → 0.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/outline.js +51 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mishasinitcyn/betterrank",
3
- "version": "0.2.10",
3
+ "version": "0.2.11",
4
4
  "description": "Structural code index with PageRank-ranked repo maps, symbol search, call-graph queries, and dependency analysis. Built on tree-sitter and graphology.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/outline.js CHANGED
@@ -133,19 +133,61 @@ function detectImportBlock(lines) {
133
133
  return { start: firstImportLine + 1, end: lastImportLine + 1, lineCount, name: null };
134
134
  }
135
135
 
136
- function outlineMode(lines, defs, pad, callerCounts) {
137
- // Mark definitions that are nested inside another definition.
138
- // Only top-level defs get their own collapse range — nested ones are swallowed
139
- // by the parent's collapse, preventing dozens of inline-callback markers.
140
- const nested = new Set();
136
+ function findImmediateParents(defs) {
137
+ const parents = new Map();
138
+
141
139
  for (const def of defs) {
140
+ let parent = null;
141
+
142
142
  for (const other of defs) {
143
143
  if (other === def) continue;
144
- if (def.lineStart > other.lineStart && def.lineEnd <= other.lineEnd) {
145
- nested.add(def);
146
- break;
144
+ if (def.lineStart <= other.lineStart || def.lineEnd > other.lineEnd) continue;
145
+
146
+ if (!parent) {
147
+ parent = other;
148
+ continue;
147
149
  }
150
+
151
+ const isCloserParent =
152
+ other.lineStart >= parent.lineStart && other.lineEnd <= parent.lineEnd;
153
+ if (isCloserParent) parent = other;
148
154
  }
155
+
156
+ parents.set(def, parent);
157
+ }
158
+
159
+ return parents;
160
+ }
161
+
162
+ function findDelegatingContainers(defs, parentMap) {
163
+ const propertyChildCounts = new Map();
164
+
165
+ for (const def of defs) {
166
+ if (def.kind !== 'property') continue;
167
+ const parent = parentMap.get(def);
168
+ if (!parent || parent.kind !== 'variable') continue;
169
+ propertyChildCounts.set(parent, (propertyChildCounts.get(parent) || 0) + 1);
170
+ }
171
+
172
+ return new Set(
173
+ [...propertyChildCounts.entries()]
174
+ .filter(([, count]) => count > 0)
175
+ .map(([def]) => def),
176
+ );
177
+ }
178
+
179
+ function outlineMode(lines, defs, pad, callerCounts) {
180
+ // Mark definitions that are nested inside another definition.
181
+ // Only defs nested inside opaque parents are swallowed.
182
+ // Some top-level variables are really structural containers, like exported
183
+ // procedure maps or routers. Those should delegate to their direct property
184
+ // children instead of collapsing the entire wrapper object.
185
+ const parentMap = findImmediateParents(defs);
186
+ const delegatingContainers = findDelegatingContainers(defs, parentMap);
187
+ const nested = new Set();
188
+ for (const def of defs) {
189
+ const parent = parentMap.get(def);
190
+ if (parent && !delegatingContainers.has(parent)) nested.add(def);
149
191
  }
150
192
 
151
193
  const collapseRanges = [];
@@ -157,6 +199,7 @@ function outlineMode(lines, defs, pad, callerCounts) {
157
199
  // Collapse all top-level definitions (functions, classes, interfaces, components)
158
200
  for (const def of defs) {
159
201
  if (nested.has(def)) continue;
202
+ if (delegatingContainers.has(def)) continue;
160
203
  if (!def.bodyStartLine) continue;
161
204
  if (def.bodyStartLine > def.lineEnd) continue;
162
205