@@ -22,7 +22,6 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext {
2222 cureditnode : pixed . PixNode ;
2323 rootnodes : pixed . PixNode [ ] ;
2424 deferrednodes : pixed . PixNode [ ] ;
25-
2625 createDiv ( parent : HTMLElement ) {
2726 this . maindiv = newDiv ( parent , "vertical-scroll" ) ;
2827 return this . maindiv [ 0 ] ;
@@ -134,6 +133,21 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext {
134133 node = node . left ;
135134 }
136135 this . cureditnode = node ;
136+ this . updateHashForSelection ( div ) ;
137+ }
138+
139+ updateHashForSelection ( div : JQuery ) {
140+ if ( typeof window === 'undefined' ) return ;
141+ var block = div ? div . closest ( '.asset_block[data-fileid]' ) : null ;
142+ var fileid = block && block . attr ( 'data-fileid' ) ;
143+ var startline = block && block . attr ( 'data-startline' ) ;
144+ var hash = '#asseteditor' ;
145+ if ( fileid && startline ) {
146+ hash += '/' + encodeURIComponent ( fileid ) + '/' + startline ;
147+ }
148+ if ( window . location . hash !== hash ) {
149+ history . replaceState ( null , '' , hash ) ;
150+ }
137151 }
138152
139153 scanFileTextForAssets ( id : string , data : string ) {
@@ -330,7 +344,9 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext {
330344 } else if ( typeof data === 'string' ) {
331345 let textfrags = this . scanFileTextForAssets ( fileid , data ) ;
332346 for ( let frag of textfrags ) {
333- const block = $ ( '<div class="asset_block"/>' ) . appendTo ( this . ensureFileDiv ( fileid ) ) ;
347+ const block = $ ( '<div class="asset_block"/>' )
348+ . attr ( { 'data-fileid' : fileid , 'data-startline' : frag . startline } )
349+ . appendTo ( this . ensureFileDiv ( fileid ) ) ;
334350 var snip = $ ( '<div class="asset_snip"/>' ) . appendTo ( block ) ;
335351 var linenos = $ ( '<span class="asset_linenos"/>' ) . appendTo ( snip ) ;
336352 $ ( '<span class="asset_lineno"/>' ) . text ( frag . startline ) . appendTo ( linenos ) ;
@@ -422,13 +438,32 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext {
422438 }
423439 } ) ;
424440 this . deferrednodes = [ ] ;
441+ this . scrollToAssetFromHash ( ) ;
425442 } else {
426443 for ( var node of this . rootnodes ) {
427444 node . refreshRight ( ) ;
428445 }
429446 }
430447 }
431448
449+ scrollToAssetFromHash ( ) : void {
450+ var hash = window . location . hash ;
451+ if ( ! hash || ! hash . startsWith ( '#asseteditor/' ) ) return ;
452+ var parts = hash . substring ( 1 ) . split ( '/' ) ; // ['asseteditor', ...filename, startline]
453+ var fileid = decodeURIComponent ( parts . slice ( 1 , - 1 ) . join ( '/' ) ) ;
454+ var startline = parts [ parts . length - 1 ] ;
455+ if ( ! fileid || ! startline ) return ;
456+ // defer to allow DOM to settle
457+ setTimeout ( ( ) => {
458+ const block = this . maindiv . find ( `.asset_block[data-fileid="${ fileid } "][data-startline="${ startline } "]` ) ;
459+ if ( block . length ) {
460+ block [ 0 ] . scrollIntoView ( { behavior : "smooth" , block : "center" } ) ;
461+ block . addClass ( 'asset_highlight' ) ;
462+ setTimeout ( ( ) => block . removeClass ( 'asset_highlight' ) , 500 ) ;
463+ }
464+ } , 0 ) ;
465+ }
466+
432467 setVisible ?( showing : boolean ) : void {
433468 // TODO: make into toolbar?
434469 if ( showing ) {
0 commit comments