@@ -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