1- import { Disposable , ExtensionContext , Uri , ViewColumn , WebviewPanel , window , workspace , Range , DecorationOptions , Position } from 'vscode' ;
1+ import {
2+ Disposable ,
3+ ExtensionContext ,
4+ Uri ,
5+ ViewColumn ,
6+ WebviewPanel ,
7+ window ,
8+ workspace ,
9+ Range ,
10+ DecorationOptions ,
11+ Position ,
12+ } from 'vscode' ;
213import * as path from 'node:path' ;
314import { execSync } from 'node:child_process' ;
415
@@ -21,9 +32,9 @@ export class LiquidProfiler {
2132 margin : '0 0 1rem 0' ,
2233 textDecoration : 'none' ,
2334 } ,
24- rangeBehavior : 1 // DecorationRangeBehavior.ClosedOpen
35+ rangeBehavior : 1 , // DecorationRangeBehavior.ClosedOpen
2536 } ) ;
26-
37+
2738 private lineDecorationType = window . createTextEditorDecorationType ( {
2839 backgroundColor : 'rgba(173, 216, 230, 0.2)' ,
2940 border : '1px solid rgba(173, 216, 230, 0.5)' ,
@@ -53,19 +64,16 @@ export class LiquidProfiler {
5364 this . _panel . title = `Liquid Profile: ${ url } ` ;
5465 this . _panel . webview . html = '' ;
5566 } else {
56- this . _panel = window . createWebviewPanel (
57- 'liquidProfile' ,
58- `Liquid Profile: ${ url } ` ,
59- column ,
60- {
61- enableScripts : true ,
62- // Allow files in the user's workspace (.tmp directory) to be used as local resources
63- localResourceRoots : [
64- ...( workspace . workspaceFolders ? workspace . workspaceFolders . map ( folder => folder . uri ) : [ ] ) ,
65- Uri . file ( this . _context . asAbsolutePath ( path . join ( 'dist' , 'node' , 'speedscope' ) ) )
66- ]
67- }
68- ) ;
67+ this . _panel = window . createWebviewPanel ( 'liquidProfile' , `Liquid Profile: ${ url } ` , column , {
68+ enableScripts : true ,
69+ // Allow files in the user's workspace (.tmp directory) to be used as local resources
70+ localResourceRoots : [
71+ ...( workspace . workspaceFolders
72+ ? workspace . workspaceFolders . map ( ( folder ) => folder . uri )
73+ : [ ] ) ,
74+ Uri . file ( this . _context . asAbsolutePath ( path . join ( 'dist' , 'node' , 'speedscope' ) ) ) ,
75+ ] ,
76+ } ) ;
6977 this . _panel . onDidDispose ( ( ) => this . dispose ( ) , null , this . _disposables ) ;
7078 }
7179
@@ -78,7 +86,9 @@ export class LiquidProfiler {
7886 }
7987
8088 private async _getSpeedscopeHtml ( profileContents : string ) {
81- const indexHtmlPath = Uri . file ( this . _context . asAbsolutePath ( path . join ( 'dist' , 'node' , 'speedscope' , 'index.html' ) ) ) ;
89+ const indexHtmlPath = Uri . file (
90+ this . _context . asAbsolutePath ( path . join ( 'dist' , 'node' , 'speedscope' , 'index.html' ) ) ,
91+ ) ;
8292 let htmlContent = Buffer . from ( await workspace . fs . readFile ( indexHtmlPath ) ) . toString ( 'utf8' ) ;
8393
8494 // Convert local resource paths to vscode-resource URIs, and replace the paths in the HTML content
@@ -96,8 +106,12 @@ export class LiquidProfiler {
96106 const tmpFile = path . join ( tmpDir ! , '.tmp' , 'profile.json' ) ;
97107 await workspace . fs . writeFile ( Uri . file ( tmpFile ) , Buffer . from ( profileContents ) ) ;
98108 const tmpUri = this . _panel ! . webview . asWebviewUri ( Uri . file ( tmpFile ) ) ;
99- htmlContent = htmlContent . replace ( '<body>' , `<body><script>window.location.hash = "profileURL=${ encodeURIComponent
100- ( tmpUri . toString ( ) ) } ";</script>`) ;
109+ htmlContent = htmlContent . replace (
110+ '<body>' ,
111+ `<body><script>window.location.hash = "profileURL=${ encodeURIComponent (
112+ tmpUri . toString ( ) ,
113+ ) } ";</script>`,
114+ ) ;
101115
102116 return htmlContent ;
103117 }
@@ -116,7 +130,7 @@ export class LiquidProfiler {
116130 /**
117131 * Calculate the execution times for each file and line in the profile.
118132 * @param profile - The parsed profile data.
119- * @returns An object containing two maps:
133+ * @returns An object containing two maps:
120134 * fileExecutionTimes: Map<string, number> - The execution time for each file.
121135 * lineExecutionTimes: Map<number, number> - The execution time for each line.
122136 */
@@ -125,7 +139,7 @@ export class LiquidProfiler {
125139 const lineExecutionTimes = new Map < SharedProfileFrame , number > ( ) ;
126140 const openEvents = new Map < number , number > ( ) ;
127141
128- profile . profiles [ 0 ] . events . forEach ( event => {
142+ profile . profiles [ 0 ] . events . forEach ( ( event ) => {
129143 const frameId = event . frame ;
130144 const frame = profile . shared . frames [ frameId ] ;
131145
@@ -136,7 +150,10 @@ export class LiquidProfiler {
136150 if ( startTime !== undefined ) {
137151 const duration = event . at - startTime ;
138152
139- if ( frame . file && ( frame . file . startsWith ( 'sections/' ) || frame . file . startsWith ( 'snippets/' ) ) ) {
153+ if (
154+ frame . file &&
155+ ( frame . file . startsWith ( 'sections/' ) || frame . file . startsWith ( 'snippets/' ) )
156+ ) {
140157 let current = lineExecutionTimes . get ( frame ) || 0 ;
141158 lineExecutionTimes . set ( frame , current + duration ) ;
142159
@@ -169,8 +186,8 @@ export class LiquidProfiler {
169186
170187 const { fileExecutionTimes, lineExecutionTimes } = this . calculateExecutionTimes ( parsedProfile ) ;
171188
172- // Check if there are any workspace folders.
173- // TODO: Is this necessary?
189+ // Check if there are any workspace folders.
190+ // TODO: Is this necessary?
174191 const workspaceFolders = workspace . workspaceFolders ;
175192 if ( ! workspaceFolders ) {
176193 console . error ( '[Liquid Profiler] No workspace folders found' ) ;
@@ -193,8 +210,8 @@ export class LiquidProfiler {
193210 after : {
194211 contentText : ` (File) ⏱️ ${ ( duration / 1000000 ) . toFixed ( 2 ) } ms` ,
195212 color : this . getColorForDuration ( duration ) ,
196- }
197- }
213+ } ,
214+ } ,
198215 } ;
199216
200217 // Store the file-level decoration.
@@ -204,15 +221,24 @@ export class LiquidProfiler {
204221 // Store the paths it's been applied to in a set.
205222 const appliedPaths = new Set < string > ( ) ;
206223 for ( const editor of visibleEditors ) {
207- if ( editor . document . uri . fsPath === uri . fsPath && ! appliedPaths . has ( editor . document . uri . fsPath ) ) {
208- console . log ( `[Liquid Profiler] Applying file decoration for ${ liquidFile } (${ ( duration / 1000000 ) . toFixed ( 2 ) } ms)
224+ if (
225+ editor . document . uri . fsPath === uri . fsPath &&
226+ ! appliedPaths . has ( editor . document . uri . fsPath )
227+ ) {
228+ console . log ( `[Liquid Profiler] Applying file decoration for ${ liquidFile } (${ (
229+ duration / 1000000
230+ ) . toFixed ( 2 ) } ms)
209231 ` ) ;
210232 editor . setDecorations ( this . fileDecorationType , [ decoration ] ) ;
211233 appliedPaths . add ( editor . document . uri . fsPath ) ;
212234 }
213235 }
214236
215- console . log ( `[Liquid Profiler] Created file decoration for ${ liquidFile } (${ ( duration / 1000000 ) . toFixed ( 2 ) } ms)` ) ;
237+ console . log (
238+ `[Liquid Profiler] Created file decoration for ${ liquidFile } (${ (
239+ duration / 1000000
240+ ) . toFixed ( 2 ) } ms)`,
241+ ) ;
216242 } catch ( err ) {
217243 console . error ( `[Liquid Profiler] Error creating file decoration for ${ fullPath } :` , err ) ;
218244 }
@@ -223,19 +249,19 @@ export class LiquidProfiler {
223249 try {
224250 const uri = Uri . file ( path . join ( rootPath , `${ frame . file } .liquid` ) ) ;
225251 const document = await workspace . openTextDocument ( uri ) ;
226- // If frame.name starts with 'variable:', then scan the line for the variable name after "variable:" and find the
252+ // If frame.name starts with 'variable:', then scan the line for the variable name after "variable:" and find the
227253 // range immediately after the variable name to apply the decoration to
228254 let range : Range | undefined ;
229255 if ( frame . name . startsWith ( 'variable:' ) || frame . name . startsWith ( 'tag:' ) ) {
230- const variableName = frame . name . split ( 'variable:' ) [ 1 ] || frame . name . split ( 'tag:' ) [ 1 ] ;
256+ const variableName = frame . name . split ( 'variable:' ) [ 1 ] || frame . name . split ( 'tag:' ) [ 1 ] ;
231257 const line = document . lineAt ( frame . line - 1 ) ;
232- const variableRange = line . text . indexOf ( variableName ) ; // 7
258+ const variableRange = line . text . indexOf ( variableName ) ; // 7
233259
234260 if ( variableRange !== - 1 ) {
235261 // Create range that covers the variable name itself using explicit positions
236262 range = new Range (
237263 new Position ( line . lineNumber , variableRange ) ,
238- new Position ( line . lineNumber , variableRange + variableName . length )
264+ new Position ( line . lineNumber , variableRange + variableName . length ) ,
239265 ) ;
240266 } else {
241267 // Fallback to full line if variable name not found
@@ -249,16 +275,18 @@ export class LiquidProfiler {
249275 }
250276 const decoration : DecorationOptions = {
251277 range : range ! ,
252- renderOptions : { after : { contentText : ` ⏱️ ${ ( duration / 1000000 ) . toFixed ( 2 ) } ms` } }
278+ renderOptions : { after : { contentText : ` ⏱️ ${ ( duration / 1000000 ) . toFixed ( 2 ) } ms` } } ,
253279 } ;
254280
255281 // Store the decoration in a map where the key is the file path and the value is an array of decorations
256282 const fileDecorations = this . _decorations . get ( uri . fsPath ) || [ ] ;
257283 fileDecorations . push ( decoration ) ;
258284 this . _decorations . set ( uri . fsPath , fileDecorations ) ;
259-
260285 } catch ( err ) {
261- console . error ( `[Liquid Profiler] Error creating line decoration for ${ frame . file } :${ frame . line } :` , err ) ;
286+ console . error (
287+ `[Liquid Profiler] Error creating line decoration for ${ frame . file } :${ frame . line } :` ,
288+ err ,
289+ ) ;
262290 }
263291 }
264292
@@ -272,7 +300,7 @@ export class LiquidProfiler {
272300
273301 // Add listener for active editor changes
274302 this . _context . subscriptions . push (
275- window . onDidChangeActiveTextEditor ( editor => {
303+ window . onDidChangeActiveTextEditor ( ( editor ) => {
276304 if ( editor ) {
277305 const decorations = this . _decorations . get ( editor . document . uri . fsPath ) ;
278306 if ( decorations ) {
@@ -282,7 +310,7 @@ export class LiquidProfiler {
282310 editor . setDecorations ( this . fileDecorationType , [ ] ) ;
283311 }
284312 }
285- } )
313+ } ) ,
286314 ) ;
287315 }
288316
@@ -292,7 +320,7 @@ export class LiquidProfiler {
292320 if ( ms < 10 ) {
293321 // Fast: Green
294322 return '#4caf50' ;
295- }
323+ }
296324 if ( ms < 50 ) {
297325 // Medium: Yellow
298326 return '#ffc107' ;
@@ -325,4 +353,3 @@ export class LiquidProfiler {
325353 }
326354 }
327355}
328-
0 commit comments