Skip to content

Commit 73f3bad

Browse files
committed
refactor(algorithms): convert hierarchical layout functions to const
- Convert function declarations to const for better tree-shaking - Fix null safety issues in buildTreeStructure - Add parentChildren null check before array push - Fix queue.shift() null check with early break - Convert toNodePositionMap to const
1 parent 0b3ad3b commit 73f3bad

File tree

1 file changed

+26
-20
lines changed

1 file changed

+26
-20
lines changed

packages/algorithms/src/layout/hierarchical-layout.ts

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ const DEFAULT_OPTIONS: Required<HierarchicalLayoutOptions> = {
6969
* For affiliation: affiliation (author affiliated with institution)
7070
* @param edge
7171
*/
72-
function isParentChildEdge(edge: GraphEdge): boolean {
72+
const isParentChildEdge = (edge: GraphEdge): boolean => {
7373
// Reference relationship: earlier works are "parents" of later works
7474
if (edge.type === 'REFERENCE') {
7575
return true;
@@ -86,19 +86,19 @@ function isParentChildEdge(edge: GraphEdge): boolean {
8686
}
8787

8888
return false;
89-
}
89+
};
9090

9191
/**
9292
* Build adjacency lists for parent-child relationships
9393
* @param nodes
9494
* @param edges
9595
* @param rootNodeId
9696
*/
97-
function buildTreeStructure(
97+
const buildTreeStructure = (
9898
nodes: GraphNode[],
9999
edges: GraphEdge[],
100100
rootNodeId: string | null
101-
): { rootNodeId: string; children: Map<string, string[]>; parents: Map<string, string> } {
101+
): { rootNodeId: string; children: Map<string, string[]>; parents: Map<string, string> } => {
102102
const children = new Map<string, string[]>();
103103
const parents = new Map<string, string>();
104104

@@ -115,6 +115,7 @@ function buildTreeStructure(
115115

116116
if (edge.type === 'AUTHORSHIP') {
117117
// Target (work) is child of source (author)
118+
// or Target (author) is child of source (institution)
118119
parent = source;
119120
child = target;
120121
} else if (edge.type === 'REFERENCE') {
@@ -133,7 +134,10 @@ function buildTreeStructure(
133134
if (!children.has(parent)) {
134135
children.set(parent, []);
135136
}
136-
children.get(parent)!.push(child);
137+
const parentChildren = children.get(parent);
138+
if (parentChildren) {
139+
parentChildren.push(child);
140+
}
137141
parents.set(child, parent);
138142
});
139143

@@ -156,19 +160,19 @@ function buildTreeStructure(
156160
}
157161

158162
return { rootNodeId: root, children, parents };
159-
}
163+
};
160164

161165
/**
162166
* Calculate subtree width for each node
163167
* @param nodeId
164168
* @param children
165169
* @param nodeSpacing
166170
*/
167-
function calculateSubtreeWidth(
171+
const calculateSubtreeWidth = (
168172
nodeId: string,
169173
children: Map<string, string[]>,
170174
nodeSpacing: number
171-
): number {
175+
): number => {
172176
const nodeChildren = children.get(nodeId);
173177
if (!nodeChildren || nodeChildren.length === 0) {
174178
return nodeSpacing;
@@ -180,7 +184,7 @@ function calculateSubtreeWidth(
180184
});
181185

182186
return totalWidth;
183-
}
187+
};
184188

185189
/**
186190
* Assign Y positions to children recursively
@@ -189,12 +193,12 @@ function calculateSubtreeWidth(
189193
* @param nodeSpacing
190194
* @param startY
191195
*/
192-
function assignChildPositions(
196+
const assignChildPositions = (
193197
nodeId: string,
194198
children: Map<string, string[]>,
195199
nodeSpacing: number,
196200
startY: number
197-
): Map<string, number> {
201+
): Map<string, number> => {
198202
const positions = new Map<string, number>();
199203
const nodeChildren = children.get(nodeId);
200204

@@ -219,7 +223,7 @@ function assignChildPositions(
219223
});
220224

221225
return positions;
222-
}
226+
};
223227

224228
/**
225229
* Apply hierarchical layout to graph
@@ -228,19 +232,19 @@ function assignChildPositions(
228232
* @param options Layout configuration
229233
* @returns Positioned nodes with layout coordinates
230234
*/
231-
export function hierarchicalLayout(
235+
export const hierarchicalLayout = (
232236
nodes: GraphNode[],
233237
edges: GraphEdge[],
234238
options: HierarchicalLayoutOptions = {}
235-
): HierarchicalLayoutResult {
239+
): HierarchicalLayoutResult => {
236240
const opts = { ...DEFAULT_OPTIONS, ...options };
237241

238242
if (nodes.length === 0) {
239243
return { nodes: [], maxDepth: 0, rootNodeId: '' };
240244
}
241245

242246
// Build tree structure
243-
const { rootNodeId, children, parents } = buildTreeStructure(nodes, edges, opts.rootNodeId);
247+
const { rootNodeId, children } = buildTreeStructure(nodes, edges, opts.rootNodeId);
244248

245249
// BFS to assign levels
246250
const levels = new Map<string, number>();
@@ -249,7 +253,9 @@ export function hierarchicalLayout(
249253
let maxDepth = 0;
250254

251255
while (queue.length > 0) {
252-
const { nodeId, level } = queue.shift()!;
256+
const shifted = queue.shift();
257+
if (!shifted) break;
258+
const { nodeId, level } = shifted;
253259
levels.set(nodeId, level);
254260
maxDepth = Math.max(maxDepth, level);
255261

@@ -294,20 +300,20 @@ export function hierarchicalLayout(
294300
maxDepth,
295301
rootNodeId,
296302
};
297-
}
303+
};
298304

299305
/**
300306
* Convert positioned nodes to a node position map for react-force-graph
301307
* @param layoutResult
302308
*/
303-
export function toNodePositionMap(
309+
export const toNodePositionMap = (
304310
layoutResult: HierarchicalLayoutResult
305-
): Map<string, { x: number; y: number }> {
311+
): Map<string, { x: number; y: number }> => {
306312
const positionMap = new Map<string, { x: number; y: number }>();
307313

308314
layoutResult.nodes.forEach(({ node, x, y }) => {
309315
positionMap.set(node.id, { x, y });
310316
});
311317

312318
return positionMap;
313-
}
319+
};

0 commit comments

Comments
 (0)