Skip to content

Commit 30b6718

Browse files
author
cahierchen
committed
feat: support text_mode collapse recursive
1 parent b0482e4 commit 30b6718

File tree

3 files changed

+79
-14
lines changed

3 files changed

+79
-14
lines changed

src/lib/components/modes/JSONEditorRoot.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@
238238
if (refTreeMode) {
239239
return refTreeMode.collapse(path, recursive)
240240
} else if (refTextMode) {
241-
return refTextMode.collapse(path)
241+
return refTextMode.collapse(path, recursive)
242242
} else {
243243
throw new Error(`Method collapse is not available in mode "${mode}"`)
244244
}

src/lib/components/modes/textmode/TextMode.svelte

Lines changed: 76 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -286,23 +286,28 @@
286286
}
287287
}
288288
289-
export function collapse(path: JSONPath) {
289+
export function collapse(path: JSONPath, recursive: boolean) {
290290
if (!codeMirrorView) {
291291
return
292292
}
293293
294294
try {
295295
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+
}
306311
}
307312
} else {
308313
foldAll(codeMirrorView)
@@ -311,6 +316,66 @@
311316
onError(err as Error)
312317
}
313318
}
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+
}
314379
315380
export function expand(path: JSONPath, callback: OnExpand = expandSelf) {
316381
if (!codeMirrorView) {

src/routes/examples/expand_collapse/+page.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
}
2121
2222
function collapseObject() {
23-
refJsonEditor.collapse(['object'])
23+
refJsonEditor.collapse(['object'], true)
2424
}
2525
2626
function expandArray() {
@@ -49,7 +49,7 @@
4949

5050
<p>
5151
<button type="button" onclick={expandObject}>Expand object</button>
52-
<button type="button" onclick={collapseObject}>Collapse object</button>
52+
<button type="button" onclick={collapseObject}>Collapse object recursive</button>
5353
<button type="button" onclick={expandArray}>Expand array</button>
5454
<button type="button" onclick={collapseArray}>Collapse array</button>
5555
</p>

0 commit comments

Comments
 (0)