|
286 | 286 | } |
287 | 287 | } |
288 | 288 |
|
289 | | - export function collapse(path: JSONPath) { |
| 289 | + export function collapse(path: JSONPath, recursive: boolean) { |
290 | 290 | if (!codeMirrorView) { |
291 | 291 | return |
292 | 292 | } |
293 | 293 |
|
294 | 294 | try { |
295 | 295 | if (path && path.length > 0) { |
296 | | - // Find the text location of the given JSON path |
297 | | - const { from } = findTextLocation(normalization.escapeValue(text), path) |
298 | | -
|
299 | | - if (from !== undefined) { |
300 | | - // Set selection to the position we want to fold |
301 | | - codeMirrorView.dispatch({ |
302 | | - selection: { anchor: from, head: from } |
303 | | - }) |
304 | | - // Use CodeMirror's foldCode command for specific path |
305 | | - foldCode(codeMirrorView) |
| 296 | + if (recursive) { |
| 297 | + // Recursively fold all nested objects and arrays |
| 298 | + collapseRecursively(path) |
| 299 | + } else { |
| 300 | + // Find the text location of the given JSON path |
| 301 | + const { from } = findTextLocation(normalization.escapeValue(text), path) |
| 302 | +
|
| 303 | + if (from !== undefined && from !== 0) { |
| 304 | + // Set selection to the position we want to fold |
| 305 | + codeMirrorView.dispatch({ |
| 306 | + selection: { anchor: from, head: from } |
| 307 | + }) |
| 308 | + // Use CodeMirror's foldCode command for specific path |
| 309 | + foldCode(codeMirrorView) |
| 310 | + } |
306 | 311 | } |
307 | 312 | } else { |
308 | 313 | foldAll(codeMirrorView) |
|
311 | 316 | onError(err as Error) |
312 | 317 | } |
313 | 318 | } |
| 319 | + function findFoldableLocations( |
| 320 | + foldableLocations: number[], |
| 321 | + currentValue: unknown, |
| 322 | + currentPath: JSONPath |
| 323 | + ) { |
| 324 | + if (currentValue && typeof currentValue === 'object' && currentValue !== null) { |
| 325 | + const { from } = findTextLocation(normalization.escapeValue(text), currentPath) |
| 326 | + if (from !== undefined && from !== 0) { |
| 327 | + foldableLocations.push(from) |
| 328 | + } |
| 329 | +
|
| 330 | + // Recursively check nested objects and arrays |
| 331 | + if (Array.isArray(currentValue)) { |
| 332 | + currentValue.forEach((item, index) => { |
| 333 | + findFoldableLocations(foldableLocations, item, currentPath.concat(String(index))) |
| 334 | + }) |
| 335 | + } else { |
| 336 | + Object.keys(currentValue as Record<string, unknown>).forEach((key) => { |
| 337 | + findFoldableLocations( |
| 338 | + foldableLocations, |
| 339 | + (currentValue as Record<string, unknown>)[key], |
| 340 | + currentPath.concat(key) |
| 341 | + ) |
| 342 | + }) |
| 343 | + } |
| 344 | + } |
| 345 | + return foldableLocations |
| 346 | + } |
| 347 | +
|
| 348 | + function collapseRecursively(path: JSONPath) { |
| 349 | + try { |
| 350 | + const json = parser.parse(text) |
| 351 | +
|
| 352 | + // Get the value at the specified path |
| 353 | + let value = json |
| 354 | + for (const segment of path) { |
| 355 | + if (value && typeof value === 'object' && value !== null && segment in value) { |
| 356 | + value = (value as Record<string, unknown>)[segment] |
| 357 | + } else { |
| 358 | + return |
| 359 | + } |
| 360 | + } |
| 361 | + // Find all foldable locations that need to be collapsed |
| 362 | + const foldableLocations: number[] = [] |
| 363 | + findFoldableLocations(foldableLocations, value, path) |
| 364 | + // Sort locations in reverse order to fold from deepest to shallowest |
| 365 | + // This prevents issues with position changes after folding |
| 366 | + foldableLocations.sort((a, b) => b - a) |
| 367 | +
|
| 368 | + // Fold each location |
| 369 | + foldableLocations.forEach((location) => { |
| 370 | + codeMirrorView.dispatch({ |
| 371 | + selection: { anchor: location, head: location } |
| 372 | + }) |
| 373 | + foldCode(codeMirrorView) |
| 374 | + }) |
| 375 | + } catch (err) { |
| 376 | + onError(err as Error) |
| 377 | + } |
| 378 | + } |
314 | 379 |
|
315 | 380 | export function expand(path: JSONPath, callback: OnExpand = expandSelf) { |
316 | 381 | if (!codeMirrorView) { |
|
0 commit comments