@@ -40,7 +40,6 @@ export function activate(context: vscode.ExtensionContext) {
4040 ) ;
4141 }
4242 ) ;
43-
4443 // Register command to add OpenAPI source
4544 let addSourceDisposable = vscode . commands . registerCommand (
4645 "openapi-ui.addSource" ,
@@ -54,28 +53,76 @@ export function activate(context: vscode.ExtensionContext) {
5453 return ;
5554 }
5655
57- const url = await vscode . window . showInputBox ( {
58- prompt : "Enter the URL of the OpenAPI specification" ,
59- placeHolder : "e.g., https://api.example.com/openapi.json" ,
60- validateInput : ( value ) => {
61- if ( ! value ) {
62- return "URL is required" ;
63- }
64- try {
65- new URL ( value ) ;
66- return null ;
67- } catch {
68- return "Please enter a valid URL" ;
69- }
70- } ,
71- } ) ;
56+ // Ask user to choose between URL and JSON content
57+ const sourceType = await vscode . window . showQuickPick (
58+ [
59+ {
60+ label : "URL" ,
61+ description : "Load from a URL endpoint" ,
62+ value : "url" ,
63+ } ,
64+ {
65+ label : "JSON Content" ,
66+ description : "Paste JSON content directly" ,
67+ value : "json" ,
68+ } ,
69+ ] ,
70+ {
71+ placeHolder : "Choose how to provide the OpenAPI specification" ,
72+ }
73+ ) ;
7274
73- if ( ! url ) {
75+ if ( ! sourceType ) {
7476 return ;
7577 }
7678
77- storage . addSource ( name , url ) ;
78- vscode . window . showInformationMessage ( `Added OpenAPI source: ${ name } ` ) ;
79+ if ( sourceType . value === "url" ) {
80+ const url = await vscode . window . showInputBox ( {
81+ prompt : "Enter the URL of the OpenAPI specification" ,
82+ placeHolder : "e.g., https://api.example.com/openapi.json" ,
83+ validateInput : ( value ) => {
84+ if ( ! value ) {
85+ return "URL is required" ;
86+ }
87+ try {
88+ new URL ( value ) ;
89+ return null ;
90+ } catch {
91+ return "Please enter a valid URL" ;
92+ }
93+ } ,
94+ } ) ;
95+
96+ if ( ! url ) {
97+ return ;
98+ }
99+
100+ storage . addSource ( name , url ) ;
101+ vscode . window . showInformationMessage ( `Added OpenAPI source: ${ name } ` ) ;
102+ } else {
103+ const jsonContent = await vscode . window . showInputBox ( {
104+ prompt : "Paste the OpenAPI JSON specification" ,
105+ placeHolder : "Paste your OpenAPI JSON content here..." ,
106+ validateInput : ( value ) => {
107+ if ( ! value ) {
108+ return "JSON content is required" ;
109+ }
110+ try {
111+ JSON . parse ( value ) ;
112+ return null ;
113+ } catch {
114+ return "Please enter valid JSON" ;
115+ }
116+ } ,
117+ } ) ;
118+
119+ if ( ! jsonContent ) {
120+ return ;
121+ }
122+
123+ storage . addJsonSource ( name , jsonContent ) ;
124+ vscode . window . showInformationMessage ( `Added OpenAPI source: ${ name } ` ) ;
125+ }
79126 }
80127 ) ;
81128
@@ -128,13 +175,11 @@ export function activate(context: vscode.ExtensionContext) {
128175 }
129176 } ) ;
130177 return ;
131- }
132-
133- // Create quick pick items
178+ } // Create quick pick items
134179 const quickPickItems = sources . map ( ( source ) => ( {
135180 label : source . name ,
136- description : source . url ,
137- detail : `Created: ${ source . createdAt . toLocaleString ( ) } ` ,
181+ description : source . type === " url" ? source . url : "JSON Content" ,
182+ detail : `Type: ${ source . type . toUpperCase ( ) } | Created: ${ source . createdAt . toLocaleString ( ) } ` ,
138183 sourceId : source . id ,
139184 } ) ) ;
140185
@@ -156,12 +201,22 @@ export function activate(context: vscode.ExtensionContext) {
156201 vscode . window . showErrorMessage ( "OpenAPI source not found" ) ;
157202 return ;
158203 }
159-
160- if ( ! source . name || ! source . url ) {
204+ if ( ! source . name ) {
161205 vscode . window . showErrorMessage ( "Invalid OpenAPI source data" ) ;
162206 return ;
163207 }
164208
209+ if ( source . type === "url" && ! source . url ) {
210+ vscode . window . showErrorMessage ( "Invalid OpenAPI source: missing URL" ) ;
211+ return ;
212+ }
213+
214+ if ( source . type === "json" && ! source . content ) {
215+ vscode . window . showErrorMessage (
216+ "Invalid OpenAPI source: missing JSON content"
217+ ) ;
218+ return ;
219+ }
165220 try {
166221 const panel = vscode . window . createWebviewPanel (
167222 "openapiSourceUI" ,
@@ -175,11 +230,21 @@ export function activate(context: vscode.ExtensionContext) {
175230 }
176231 ) ;
177232
178- panel . webview . html = getWebviewContent (
179- panel . webview ,
180- context . extensionPath ,
181- source . url
182- ) ;
233+ if ( source . type === "url" ) {
234+ panel . webview . html = getWebviewContent (
235+ panel . webview ,
236+ context . extensionPath ,
237+ source . url
238+ ) ;
239+ } else {
240+ // For JSON content, create a blob URL
241+ panel . webview . html = getWebviewContent (
242+ panel . webview ,
243+ context . extensionPath ,
244+ undefined ,
245+ source . content
246+ ) ;
247+ }
183248
184249 vscode . window . showInformationMessage (
185250 `Loaded OpenAPI source: ${ source . name } `
@@ -191,12 +256,64 @@ export function activate(context: vscode.ExtensionContext) {
191256 }
192257 }
193258 ) ;
259+ // Register command to add JSON OpenAPI source
260+ let addJsonSourceDisposable = vscode . commands . registerCommand (
261+ "openapi-ui.addJsonSource" ,
262+ async ( ) => {
263+ const name = await vscode . window . showInputBox ( {
264+ prompt : "Enter a name for the OpenAPI source" ,
265+ placeHolder : "e.g., My Custom API" ,
266+ } ) ;
267+
268+ if ( ! name ) {
269+ return ;
270+ }
271+
272+ const jsonContent = await vscode . window . showInputBox ( {
273+ prompt : "Paste the OpenAPI JSON specification" ,
274+ placeHolder : "Paste your OpenAPI JSON content here..." ,
275+ validateInput : ( value ) => {
276+ if ( ! value ) {
277+ return "JSON content is required" ;
278+ }
279+ try {
280+ JSON . parse ( value ) ;
281+ return null ;
282+ } catch {
283+ return "Please enter valid JSON" ;
284+ }
285+ } ,
286+ } ) ;
287+
288+ if ( ! jsonContent ) {
289+ return ;
290+ }
291+ try {
292+ storage . addJsonSource ( name , jsonContent ) ;
293+ vscode . window . showInformationMessage (
294+ `Added and opened OpenAPI source: ${ name } `
295+ ) ;
296+
297+ // Automatically load the source we just added
298+ const sources = storage . getSources ( ) ;
299+ const newSource = sources . find ( ( s ) => s . name === name ) ;
300+ if ( newSource ) {
301+ vscode . commands . executeCommand ( "openapi-ui.loadSource" , newSource . id ) ;
302+ }
303+ } catch ( error ) {
304+ vscode . window . showErrorMessage (
305+ `Failed to add OpenAPI source: ${ error } `
306+ ) ;
307+ }
308+ }
309+ ) ;
194310 context . subscriptions . push (
195311 openViewDisposable ,
196312 addSourceDisposable ,
197313 removeSourceDisposable ,
198314 refreshSourcesDisposable ,
199- loadSourceDisposable
315+ loadSourceDisposable ,
316+ addJsonSourceDisposable
200317 ) ;
201318}
202319
@@ -205,7 +322,8 @@ export function deactivate() {}
205322function getWebviewContent (
206323 webview : vscode . Webview ,
207324 extensionPath : string ,
208- openapiUrl ?: string
325+ openapiUrl ?: string ,
326+ jsonContent ?: string
209327) : string {
210328 // Path to the core/dist directory
211329 const distPath = path . join ( extensionPath , "core-dist" ) ;
@@ -233,9 +351,15 @@ function getWebviewContent(
233351 `src="${ imgUri } "`
234352 ) ;
235353
236- // Replace the OpenAPI URL placeholder if provided
354+ // Handle OpenAPI source replacement
237355 if ( openapiUrl ) {
356+ // For URL sources, replace with the provided URL
238357 htmlContent = htmlContent . replace ( "#swagger_path#" , openapiUrl ) ;
358+ } else if ( jsonContent ) {
359+ // For JSON sources, create a blob URL and inject the content
360+ const encodedContent = Buffer . from ( jsonContent ) . toString ( "base64" ) ;
361+ const dataUrl = `data:application/json;base64,${ encodedContent } ` ;
362+ htmlContent = htmlContent . replace ( "#swagger_path#" , dataUrl ) ;
239363 }
240364
241365 return htmlContent ;
0 commit comments