@@ -100,7 +100,14 @@ export function validateConfig(document: TextDocument): Diagnostic[] {
100
100
101
101
let validate ;
102
102
try {
103
- validate = ajv . compile ( schemaInfo . schema ) ;
103
+ // Create a copy of the schema and modify $ref to use Draft 07 instead of Draft 04
104
+ const modifiedSchema = JSON . parse ( JSON . stringify ( schemaInfo . schema ) ) ;
105
+ if (
106
+ modifiedSchema . $schema === "http://json-schema.org/draft-04/schema#"
107
+ ) {
108
+ modifiedSchema . $schema = "http://json-schema.org/draft-07/schema#" ;
109
+ }
110
+ validate = ajv . compile ( modifiedSchema ) ;
104
111
} catch ( schemaError ) {
105
112
console . error ( `[JSON_CONFIG] Failed to compile schema:` , schemaError ) ;
106
113
return [ ] ;
@@ -281,6 +288,33 @@ export function getConfigCompletions(document: TextDocument): CompletionItem[] {
281
288
) ;
282
289
}
283
290
291
+ // Helper function to detect if JSON is minified (single line without meaningful whitespace)
292
+ function isMinifiedJson ( jsonContent : string ) : boolean {
293
+ const lineCount = jsonContent . split ( "\n" ) . length ;
294
+ const trimmed = jsonContent . trim ( ) ;
295
+
296
+ // Consider it minified if it's just one line, or if it's very compact
297
+ return lineCount === 1 || ( lineCount <= 3 && trimmed . length < 200 ) ;
298
+ }
299
+
300
+ // Helper function to normalize JSON content for position calculations
301
+ // Only formats if the JSON appears to be truly minified (single line)
302
+ function normalizeJsonContent ( jsonContent : string ) : string {
303
+ try {
304
+ // Only format if it's clearly minified (single line with no meaningful line breaks)
305
+ if ( isMinifiedJson ( jsonContent ) ) {
306
+ const parsed = JSON . parse ( jsonContent ) ;
307
+ return JSON . stringify ( parsed , null , 2 ) ;
308
+ }
309
+
310
+ // Otherwise, use original content to preserve manual formatting
311
+ return jsonContent ;
312
+ } catch {
313
+ // If parsing fails, return original content
314
+ return jsonContent ;
315
+ }
316
+ }
317
+
284
318
export function getConfigHover (
285
319
document : TextDocument ,
286
320
position : Position ,
@@ -303,16 +337,62 @@ export function getConfigHover(
303
337
return null ;
304
338
}
305
339
306
- const line = document . getText (
307
- Range . create ( position . line , 0 , position . line , 1000 ) ,
340
+ // Normalize the JSON content for position calculations
341
+ const originalContent = document . getText ( ) ;
342
+ const normalizedContent = normalizeJsonContent ( originalContent ) ;
343
+
344
+ // Split into lines for position calculation
345
+ const formattedLines = normalizedContent . split ( "\n" ) ;
346
+
347
+ // Make sure the position is valid
348
+ if ( position . line >= formattedLines . length ) {
349
+ return null ;
350
+ }
351
+
352
+ const line = formattedLines [ position . line ] ;
353
+
354
+ // Find all quoted strings on the line with their positions
355
+ const quotes = [ ] ;
356
+ const regex = / " ( [ ^ " ] + ) " / g;
357
+ let match ;
358
+ while ( ( match = regex . exec ( line ) ) !== null ) {
359
+ quotes . push ( {
360
+ text : match [ 0 ] ,
361
+ value : match [ 1 ] ,
362
+ start : match . index ,
363
+ end : match . index + match [ 0 ] . length ,
364
+ } ) ;
365
+ }
366
+
367
+ // Find which quote contains the cursor position
368
+ const cursorQuote = quotes . find (
369
+ ( q ) => position . character >= q . start && position . character <= q . end ,
308
370
) ;
309
- const match = line . match ( / " ( [ ^ " ] + ) " / ) ;
310
371
311
- if ( ! match ) {
372
+ if ( ! cursorQuote ) {
312
373
return null ;
313
374
}
314
375
315
- const propertyName = match [ 1 ] ;
376
+ // Check if this is a property key (followed by colon) or property value
377
+ const isPropertyKey = line . substring ( cursorQuote . end ) . trim ( ) . startsWith ( ":" ) ;
378
+
379
+ let propertyName ;
380
+ if ( isPropertyKey ) {
381
+ // This is a property key, use it directly
382
+ propertyName = cursorQuote . value ;
383
+ } else {
384
+ // This is a property value, try to find the corresponding key
385
+ // Look backwards to find the property key
386
+ const beforeCursor = line . substring ( 0 , cursorQuote . start ) ;
387
+ const keyMatch = beforeCursor . match ( / " ( [ ^ " ] + ) " \s * : \s * [ ^ : ] * $ / ) ;
388
+ if ( keyMatch ) {
389
+ propertyName = keyMatch [ 1 ] ;
390
+ } else {
391
+ // If we can't find the key, this might be an array value or nested property
392
+ return null ;
393
+ }
394
+ }
395
+
316
396
const property = schemaInfo . schema . properties [ propertyName ] ;
317
397
318
398
if ( property ?. description ) {
0 commit comments