@@ -29,7 +29,6 @@ export function TemplateViewer({
2929 onResourceDoubleClick,
3030} : TemplateViewerProps ) : JSX . Element {
3131 const [ format , setFormat ] = React . useState < Format > ( 'yaml' ) ;
32- const [ collapsedResources , setCollapsedResources ] = React . useState < Set < string > > ( new Set ( ) ) ;
3332
3433 const { displayContent, displayResources, sections } = React . useMemo ( ( ) => {
3534 if ( format === 'json' ) {
@@ -42,71 +41,23 @@ export function TemplateViewer({
4241 return jsonToYaml ( jsonContent ) ;
4342 } , [ jsonContent , resources , format ] ) ;
4443
45- const filteredContent = React . useMemo ( ( ) => {
46- if ( collapsedResources . size === 0 ) return displayContent ;
47- return collapseContent ( displayContent , sections , collapsedResources ) ;
48- } , [ displayContent , sections , collapsedResources ] ) ;
49-
5044 // Resolve the highlight from the rendered format's own ranges (JSON block in
51- // JSON view, YAML block in YAML view), so the highlight is always in the
52- // coordinate system actually on screen. Derived, so toggling format re-resolves.
53- const adjustedHighlight = React . useMemo ( ( ) => {
45+ // JSON view, YAML block in YAML view), so it is always in the coordinate
46+ // system on screen. Derived, so toggling format re-resolves.
47+ const highlight = React . useMemo ( ( ) => {
5448 const block = highlightLogicalId ? displayResources [ highlightLogicalId ] ?. block : undefined ;
55- if ( ! block ) return undefined ;
56- if ( collapsedResources . size === 0 ) return { start : block . startLine , end : block . endLine } ;
57- return adjustLineNumbers ( block . startLine , block . endLine , sections , collapsedResources ) ;
58- } , [ highlightLogicalId , displayResources , sections , collapsedResources ] ) ;
59-
60- const toggleResource = React . useCallback ( ( logicalId : string ) => {
61- setCollapsedResources ( ( prev ) => {
62- const next = new Set ( prev ) ;
63- if ( next . has ( logicalId ) ) {
64- next . delete ( logicalId ) ;
65- } else {
66- next . add ( logicalId ) ;
67- }
68- return next ;
69- } ) ;
70- } , [ ] ) ;
49+ return block ? { start : block . startLine , end : block . endLine } : undefined ;
50+ } , [ highlightLogicalId , displayResources ] ) ;
7151
7252 const handleDoubleClick = React . useCallback ( ( line : number ) => {
73- const originalLine = collapsedResources . size === 0
74- ? line
75- : reverseAdjustLine ( line , sections , collapsedResources ) ;
76-
77- // Check if the user double-clicked a collapse placeholder
78- const lines = filteredContent . split ( '\n' ) ;
79- const clickedLine = lines [ line - 1 ] ?? '' ;
80- if ( clickedLine . includes ( '▸' ) && clickedLine . includes ( '(collapsed)' ) ) {
81- const match = clickedLine . match ( / ▸ \s + ( \S + ) / ) ;
82- if ( match ) {
83- toggleResource ( match [ 1 ] ) ;
84- return ;
85- }
86- }
87-
88- if ( onResourceDoubleClick ) {
89- // Map the clicked line back to the resource that owns it (display-coordinate
90- // sections), so the reverse jump is identity-based like the forward one.
91- const section = sections . find ( ( s ) => originalLine >= s . startLine && originalLine <= s . endLine ) ;
92- if ( section ) {
93- onResourceDoubleClick ( section . logicalId ) ;
94- }
95- }
96- } , [ filteredContent , sections , collapsedResources , onResourceDoubleClick , toggleResource ] ) ;
97-
98- const gutterDecorations = React . useMemo ( ( ) => {
99- const decorations = new Map < number , { icon : string ; logicalId : string } > ( ) ;
100- for ( const section of sections ) {
101- const adjustedLine = collapsedResources . size === 0
102- ? section . startLine
103- : adjustSingleLine ( section . startLine , sections , collapsedResources ) ;
104- if ( adjustedLine !== undefined && ! collapsedResources . has ( section . logicalId ) ) {
105- decorations . set ( adjustedLine , { icon : '▾' , logicalId : section . logicalId } ) ;
106- }
53+ if ( ! onResourceDoubleClick ) return ;
54+ // Map the clicked line back to the resource that owns it, so the reverse
55+ // jump is identity-based like the forward one.
56+ const section = sections . find ( ( s ) => line >= s . startLine && line <= s . endLine ) ;
57+ if ( section ) {
58+ onResourceDoubleClick ( section . logicalId ) ;
10759 }
108- return decorations ;
109- } , [ sections , collapsedResources ] ) ;
60+ } , [ sections , onResourceDoubleClick ] ) ;
11061
11162 return (
11263 < div style = { WRAPPER_STYLE } >
@@ -121,26 +72,15 @@ export function TemplateViewer({
12172 style = { format === 'json' ? TOGGLE_ACTIVE_STYLE : TOGGLE_STYLE }
12273 onClick = { ( ) => setFormat ( 'json' ) }
12374 > JSON</ button >
124- { sections . length > 0 && (
125- < >
126- < span style = { SEPARATOR_STYLE } > |</ span >
127- < button type = "button" style = { TOGGLE_STYLE } onClick = { ( ) => setCollapsedResources ( new Set ( sections . map ( ( s ) => s . logicalId ) ) ) } >
128- Collapse All
129- </ button >
130- < button type = "button" style = { TOGGLE_STYLE } onClick = { ( ) => setCollapsedResources ( new Set ( ) ) } >
131- Expand All
132- </ button >
133- </ >
134- ) }
13575 </ div >
13676 < CodeViewer
137- content = { filteredContent }
77+ content = { displayContent }
13878 language = { format }
139- highlightStart = { adjustedHighlight ?. start }
140- highlightEnd = { adjustedHighlight ?. end }
79+ highlightStart = { highlight ?. start }
80+ highlightEnd = { highlight ?. end }
14181 highlightColor = { highlightColor }
14282 navCounter = { navCounter }
143- scrollToLine = { adjustedHighlight ?. start }
83+ scrollToLine = { highlight ?. start }
14484 onLineDoubleClick = { handleDoubleClick }
14585 />
14686 </ div >
@@ -195,76 +135,6 @@ function jsonToYaml(jsonContent: string): YamlResult {
195135 return { displayContent, displayResources, sections : buildSections ( displayResources ) } ;
196136}
197137
198- function collapseContent ( content : string , sections : ResourceSection [ ] , collapsed : Set < string > ) : string {
199- const lines = content . split ( '\n' ) ;
200- const result : string [ ] = [ ] ;
201- let i = 0 ;
202-
203- const sortedSections = [ ...sections ] . sort ( ( a , b ) => a . startLine - b . startLine ) ;
204-
205- while ( i < lines . length ) {
206- const lineNum = i + 1 ;
207- const section = sortedSections . find ( ( s ) => lineNum === s . startLine && collapsed . has ( s . logicalId ) ) ;
208- if ( section ) {
209- result . push ( lines [ i ] ) ;
210- result . push ( ` ▸ ${ section . logicalId } (collapsed — double-click to expand)` ) ;
211- i = section . endLine ;
212- } else {
213- result . push ( lines [ i ] ) ;
214- i ++ ;
215- }
216- }
217-
218- return result . join ( '\n' ) ;
219- }
220-
221- function adjustLineNumbers (
222- start : number ,
223- end : number ,
224- sections : ResourceSection [ ] ,
225- collapsed : Set < string > ,
226- ) : { start : number ; end : number } | undefined {
227- const adjustedStart = adjustSingleLine ( start , sections , collapsed ) ;
228- const adjustedEnd = adjustSingleLine ( end , sections , collapsed ) ;
229- if ( adjustedStart === undefined || adjustedEnd === undefined ) return undefined ;
230- return { start : adjustedStart , end : adjustedEnd } ;
231- }
232-
233- function adjustSingleLine (
234- line : number ,
235- sections : ResourceSection [ ] ,
236- collapsed : Set < string > ,
237- ) : number | undefined {
238- let offset = 0 ;
239- for ( const section of [ ...sections ] . sort ( ( a , b ) => a . startLine - b . startLine ) ) {
240- if ( ! collapsed . has ( section . logicalId ) ) continue ;
241- const collapsedLines = section . endLine - section . startLine - 1 ;
242- if ( line > section . startLine && line <= section . endLine ) {
243- return undefined ;
244- }
245- if ( line > section . endLine ) {
246- offset += collapsedLines - 1 ;
247- }
248- }
249- return line - offset ;
250- }
251-
252- function reverseAdjustLine (
253- displayLine : number ,
254- sections : ResourceSection [ ] ,
255- collapsed : Set < string > ,
256- ) : number {
257- let offset = 0 ;
258- for ( const section of [ ...sections ] . sort ( ( a , b ) => a . startLine - b . startLine ) ) {
259- if ( ! collapsed . has ( section . logicalId ) ) continue ;
260- const collapsedLines = section . endLine - section . startLine - 1 ;
261- if ( displayLine > section . startLine - offset ) {
262- offset += collapsedLines - 1 ;
263- }
264- }
265- return displayLine + offset ;
266- }
267-
268138const WRAPPER_STYLE : React . CSSProperties = {
269139 display : 'flex' ,
270140 flexDirection : 'column' ,
@@ -297,8 +167,3 @@ const TOGGLE_ACTIVE_STYLE: React.CSSProperties = {
297167 color : '#ffffff' ,
298168 borderColor : '#0972d3' ,
299169} ;
300-
301- const SEPARATOR_STYLE : React . CSSProperties = {
302- color : '#d1d5db' ,
303- margin : '0 4px' ,
304- } ;
0 commit comments