1- import * as vscode from ' vscode' ;
1+ import * as vscode from " vscode" ;
22
33/**
44 * Provider for learningmap custom editor.
55 * Handles the webview that displays the LearningMapEditor component.
66 */
7- export class LearningmapEditorProvider implements vscode . CustomTextEditorProvider {
8- private static readonly viewType = 'learningmap.editor' ;
7+ export class LearningmapEditorProvider
8+ implements vscode . CustomTextEditorProvider
9+ {
10+ private static readonly viewType = "learningmap.editor" ;
911 private activeWebviewPanel : vscode . WebviewPanel | undefined ;
1012
1113 constructor ( private readonly context : vscode . ExtensionContext ) { }
@@ -16,7 +18,7 @@ export class LearningmapEditorProvider implements vscode.CustomTextEditorProvide
1618 public sendCommandToActiveEditor ( command : string ) : void {
1719 if ( this . activeWebviewPanel ) {
1820 this . activeWebviewPanel . webview . postMessage ( {
19- type : ' command' ,
21+ type : " command" ,
2022 command : command ,
2123 } ) ;
2224 }
@@ -28,25 +30,25 @@ export class LearningmapEditorProvider implements vscode.CustomTextEditorProvide
2830 public async resolveCustomTextEditor (
2931 document : vscode . TextDocument ,
3032 webviewPanel : vscode . WebviewPanel ,
31- _token : vscode . CancellationToken
33+ _token : vscode . CancellationToken ,
3234 ) : Promise < void > {
3335 // Track this as the active webview panel
3436 this . activeWebviewPanel = webviewPanel ;
35-
37+
3638 // Clear active panel when disposed
3739 webviewPanel . onDidDispose ( ( ) => {
3840 if ( this . activeWebviewPanel === webviewPanel ) {
3941 this . activeWebviewPanel = undefined ;
4042 }
4143 } ) ;
42-
44+
4345 // Update active panel on focus
4446 webviewPanel . onDidChangeViewState ( ( ) => {
4547 if ( webviewPanel . active ) {
4648 this . activeWebviewPanel = webviewPanel ;
4749 }
4850 } ) ;
49-
51+
5052 // Setup initial webview content
5153 webviewPanel . webview . options = {
5254 enableScripts : true ,
@@ -60,7 +62,7 @@ export class LearningmapEditorProvider implements vscode.CustomTextEditorProvide
6062 const updateWebview = ( ) => {
6163 isUpdatingFromDocument = true ;
6264 webviewPanel . webview . postMessage ( {
63- type : ' update' ,
65+ type : " update" ,
6466 content : document . getText ( ) ,
6567 } ) ;
6668 // Reset flag after a short delay
@@ -73,38 +75,47 @@ export class LearningmapEditorProvider implements vscode.CustomTextEditorProvide
7375 updateWebview ( ) ;
7476
7577 // Listen for changes in the document (from external sources)
76- const changeDocumentSubscription = vscode . workspace . onDidChangeTextDocument ( e => {
77- if ( e . document . uri . toString ( ) === document . uri . toString ( ) && e . contentChanges . length > 0 ) {
78- // Only update if change was from external source (not from us)
79- if ( ! isUpdatingFromDocument ) {
80- updateWebview ( ) ;
78+ const changeDocumentSubscription = vscode . workspace . onDidChangeTextDocument (
79+ ( e ) => {
80+ if (
81+ e . document . uri . toString ( ) === document . uri . toString ( ) &&
82+ e . contentChanges . length > 0
83+ ) {
84+ // Only update if change was from external source (not from us)
85+ if ( ! isUpdatingFromDocument ) {
86+ updateWebview ( ) ;
87+ }
8188 }
82- }
83- } ) ;
89+ } ,
90+ ) ;
8491
8592 // Handle document save event
86- const saveDocumentSubscription = vscode . workspace . onWillSaveTextDocument ( async e => {
87- if ( e . document . uri . toString ( ) === document . uri . toString ( ) ) {
88- // Wait for the save event to complete
89- e . waitUntil ( new Promise < void > ( ( resolve ) => {
90- // Send save command to webview
91- webviewPanel . webview . postMessage ( {
92- type : 'command' ,
93- command : 'save' ,
94- } ) ;
95-
96- // Wait a bit for the webview to respond
97- setTimeout ( ( ) => {
98- resolve ( ) ;
99- } , 100 ) ;
100- } ) ) ;
101- }
102- } ) ;
93+ const saveDocumentSubscription = vscode . workspace . onWillSaveTextDocument (
94+ async ( e ) => {
95+ if ( e . document . uri . toString ( ) === document . uri . toString ( ) ) {
96+ // Wait for the save event to complete
97+ e . waitUntil (
98+ new Promise < void > ( ( resolve ) => {
99+ // Send save command to webview
100+ webviewPanel . webview . postMessage ( {
101+ type : "command" ,
102+ command : "save" ,
103+ } ) ;
104+
105+ // Wait a bit for the webview to respond
106+ setTimeout ( ( ) => {
107+ resolve ( ) ;
108+ } , 100 ) ;
109+ } ) ,
110+ ) ;
111+ }
112+ } ,
113+ ) ;
103114
104115 // Listen for messages from the webview
105- webviewPanel . webview . onDidReceiveMessage ( async e => {
116+ webviewPanel . webview . onDidReceiveMessage ( async ( e ) => {
106117 switch ( e . type ) {
107- case ' change' :
118+ case " change" :
108119 // Content changed in the webview - update the document to mark it as dirty
109120 // Set flag to prevent circular updates
110121 isUpdatingFromDocument = true ;
@@ -114,12 +125,12 @@ export class LearningmapEditorProvider implements vscode.CustomTextEditorProvide
114125 isUpdatingFromDocument = false ;
115126 } , 200 ) ;
116127 return ;
117- case ' save' :
128+ case " save" :
118129 if ( ! isUpdatingFromDocument ) {
119130 await this . saveDocument ( document , e . content ) ;
120131 }
121132 return ;
122- case ' ready' :
133+ case " ready" :
123134 // Webview is ready, send initial content
124135 updateWebview ( ) ;
125136 return ;
@@ -136,17 +147,25 @@ export class LearningmapEditorProvider implements vscode.CustomTextEditorProvide
136147 /**
137148 * Write out the JSON to a given document.
138149 */
139- private async saveDocument ( document : vscode . TextDocument , json : any ) : Promise < void > {
150+ private async saveDocument (
151+ document : vscode . TextDocument ,
152+ json : any ,
153+ ) : Promise < void > {
140154 const edit = new vscode . WorkspaceEdit ( ) ;
141155
142156 // Format the JSON with 2-space indentation
143157 const text = JSON . stringify ( json , null , 2 ) ;
144158
159+ if ( document . getText ( ) == text ) {
160+ // No changes
161+ return ;
162+ }
163+
145164 // Replace the entire document
146165 edit . replace (
147166 document . uri ,
148167 new vscode . Range ( 0 , 0 , document . lineCount , 0 ) ,
149- text
168+ text ,
150169 ) ;
151170
152171 await vscode . workspace . applyEdit ( edit ) ;
@@ -158,10 +177,10 @@ export class LearningmapEditorProvider implements vscode.CustomTextEditorProvide
158177 private getHtmlForWebview ( webview : vscode . Webview ) : string {
159178 // Get URIs for scripts and styles
160179 const scriptUri = webview . asWebviewUri (
161- vscode . Uri . joinPath ( this . context . extensionUri , ' dist' , ' webview.js' )
180+ vscode . Uri . joinPath ( this . context . extensionUri , " dist" , " webview.js" ) ,
162181 ) ;
163182 const styleUri = webview . asWebviewUri (
164- vscode . Uri . joinPath ( this . context . extensionUri , ' dist' , ' webview.css' )
183+ vscode . Uri . joinPath ( this . context . extensionUri , " dist" , " webview.css" ) ,
165184 ) ;
166185
167186 // Use a nonce to only allow specific scripts to be run
@@ -201,7 +220,7 @@ function getNonce() {
201220 // Generate a cryptographically secure random string
202221 // This works in both Node.js and browser environments
203222 const array = new Uint32Array ( 8 ) ;
204- if ( typeof crypto !== ' undefined' && crypto . getRandomValues ) {
223+ if ( typeof crypto !== " undefined" && crypto . getRandomValues ) {
205224 // Browser or modern Node.js with Web Crypto API
206225 crypto . getRandomValues ( array ) ;
207226 } else {
@@ -210,5 +229,5 @@ function getNonce() {
210229 array [ i ] = Math . floor ( Math . random ( ) * 0xffffffff ) ;
211230 }
212231 }
213- return Array . from ( array , num => num . toString ( 16 ) . padStart ( 8 , '0' ) ) . join ( '' ) ;
232+ return Array . from ( array , ( num ) => num . toString ( 16 ) . padStart ( 8 , "0" ) ) . join ( "" ) ;
214233}
0 commit comments