@@ -97,8 +97,10 @@ export function create(
97
97
// https://vuejs.org/api/built-in-directives.html#v-bind
98
98
const vOnModifiers : Record < string , string > = { } ;
99
99
const vBindModifiers : Record < string , string > = { } ;
100
+ const vModelModifiers : Record < string , string > = { } ;
100
101
const vOn = builtInData . globalAttributes ?. find ( x => x . name === 'v-on' ) ;
101
102
const vBind = builtInData . globalAttributes ?. find ( x => x . name === 'v-bind' ) ;
103
+ const vModel = builtInData . globalAttributes ?. find ( x => x . name === 'v-model' ) ;
102
104
103
105
if ( vOn ) {
104
106
const markdown = ( typeof vOn . description === 'string' ? vOn . description : vOn . description ?. value ) ?? '' ;
@@ -122,6 +124,13 @@ export function create(
122
124
vBindModifiers [ name ] = desc ;
123
125
}
124
126
}
127
+ if ( vModel ) {
128
+ for ( const modifier of modelData . globalAttributes ?? [ ] ) {
129
+ const description = typeof modifier . description === 'object' ? modifier . description . value : modifier . description ;
130
+ const references = modifier . references ?. map ( ref => `[${ ref . name } ](${ ref . url } )` ) . join ( ' | ' ) ;
131
+ vModelModifiers [ modifier . name ] = description + '\n\n' + references ;
132
+ }
133
+ }
125
134
126
135
const disposable = context . env . onDidChangeConfiguration ?.( ( ) => initializing = undefined ) ;
127
136
@@ -455,81 +464,52 @@ export function create(
455
464
456
465
function afterHtmlCompletion ( completionList : vscode . CompletionList , document : TextDocument ) {
457
466
458
- do {
459
- const replacement = getReplacement ( completionList , document ) ;
460
- if ( ! replacement ) {
461
- break ;
462
- }
467
+ addDirectiveModifiers ( ) ;
463
468
464
- const hasModifier = replacement . text . includes ( '.' ) ;
465
- if ( ! hasModifier ) {
466
- break ;
469
+ function addDirectiveModifiers ( ) {
470
+ const replacement = getReplacement ( completionList , document ) ;
471
+ if ( ! replacement ?. text . includes ( '.' ) ) {
472
+ return ;
467
473
}
468
474
469
475
const [ text , ...modifiers ] = replacement . text . split ( '.' ) ;
470
476
const isVOn = text . startsWith ( 'v-on:' ) || text . startsWith ( '@' ) && text . length > 1 ;
471
477
const isVBind = text . startsWith ( 'v-bind:' ) || text . startsWith ( ':' ) && text . length > 1 ;
472
478
const isVModel = text . startsWith ( 'v-model:' ) || text === 'v-model' ;
473
- const validModifiers =
479
+ const currentModifiers =
474
480
isVOn ? vOnModifiers
475
481
: isVBind ? vBindModifiers
476
- : undefined ;
477
-
478
- if ( validModifiers ) {
479
-
480
- for ( const modifier in validModifiers ) {
481
-
482
- if ( modifiers . includes ( modifier ) ) {
483
- continue ;
484
- }
485
-
486
- const description = validModifiers [ modifier ] ;
487
- const insertText = text + modifiers . slice ( 0 , - 1 ) . map ( m => '.' + m ) . join ( '' ) + '.' + modifier ;
488
- const newItem : html . CompletionItem = {
489
- label : modifier ,
490
- filterText : insertText ,
491
- documentation : {
492
- kind : 'markdown' ,
493
- value : description ,
494
- } ,
495
- textEdit : {
496
- range : replacement . textEdit . range ,
497
- newText : insertText ,
498
- } ,
499
- kind : 20 satisfies typeof vscode . CompletionItemKind . EnumMember ,
500
- } ;
482
+ : isVModel ? vModelModifiers
483
+ : undefined ;
501
484
502
- completionList . items . push ( newItem ) ;
503
- }
485
+ if ( ! currentModifiers ) {
486
+ return ;
504
487
}
505
- else if ( isVModel ) {
506
-
507
- for ( const modifier of modelData . globalAttributes ?? [ ] ) {
508
488
509
- if ( modifiers . includes ( modifier . name ) ) {
510
- continue ;
511
- }
489
+ for ( const modifier in currentModifiers ) {
490
+ if ( modifiers . includes ( modifier ) ) {
491
+ continue ;
492
+ }
512
493
513
- const insertText = text + modifiers . slice ( 0 , - 1 ) . map ( m => '.' + m ) . join ( '' ) + '.' + modifier . name ;
514
- const newItem : html . CompletionItem = {
515
- label : modifier . name ,
516
- filterText : insertText ,
517
- documentation : {
518
- kind : 'markdown' ,
519
- value : ( typeof modifier . description === 'object' ? modifier . description . value : modifier . description )
520
- + '\n\n' + modifier . references ?. map ( ref => `[ ${ ref . name } ]( ${ ref . url } )` ) . join ( ' | ' ) ,
521
- } ,
522
- textEdit : {
523
- range : replacement . textEdit . range ,
524
- newText : insertText ,
525
- } ,
526
- kind : 20 satisfies typeof vscode . CompletionItemKind . EnumMember ,
527
- } ;
494
+ const description = currentModifiers [ modifier ] ;
495
+ const insertText = text + modifiers . slice ( 0 , - 1 ) . map ( m => '.' + m ) . join ( '' ) + '.' + modifier ;
496
+ const newItem : html . CompletionItem = {
497
+ label : modifier ,
498
+ filterText : insertText ,
499
+ documentation : {
500
+ kind : 'markdown' ,
501
+ value : description ,
502
+ } ,
503
+ textEdit : {
504
+ range : replacement . textEdit . range ,
505
+ newText : insertText ,
506
+ } ,
507
+ kind : 20 satisfies typeof vscode . CompletionItemKind . EnumMember ,
508
+ } ;
528
509
529
- completionList . items . push ( newItem ) ;
530
- }
510
+ completionList . items . push ( newItem ) ;
531
511
}
532
- } while ( 0 ) ;
512
+ }
533
513
534
514
completionList . items = completionList . items . filter ( item => ! specialTags . has ( parseLabel ( item . label ) . name ) ) ;
535
515
@@ -543,13 +523,13 @@ export function create(
543
523
}
544
524
545
525
for ( const item of completionList . items ) {
546
- const parsedLabelKey = parseItemKey ( item . label ) ;
526
+ const parsedLabel = parseItemKey ( item . label ) ;
547
527
548
- if ( parsedLabelKey ) {
549
- const name = parsedLabelKey . tag ;
550
- item . label = parsedLabelKey . leadingSlash ? '/' + name : name ;
528
+ if ( parsedLabel ) {
529
+ const name = parsedLabel . tag ;
530
+ item . label = parsedLabel . leadingSlash ? '/' + name : name ;
551
531
552
- const text = parsedLabelKey . leadingSlash ? `/${ name } >` : name ;
532
+ const text = parsedLabel . leadingSlash ? `/${ name } >` : name ;
553
533
if ( item . textEdit ) {
554
534
item . textEdit . newText = text ;
555
535
} ;
@@ -561,20 +541,19 @@ export function create(
561
541
}
562
542
}
563
543
564
- const itemKeyStr = typeof item . documentation === 'string' ? item . documentation : item . documentation ?. value ;
565
-
566
- let parsedItemKey = itemKeyStr ? parseItemKey ( itemKeyStr ) : undefined ;
544
+ const itemKey = typeof item . documentation === 'string' ? item . documentation : item . documentation ?. value ;
545
+ let parsedItem = itemKey ? parseItemKey ( itemKey ) : undefined ;
567
546
let propInfo : ComponentPropInfo | undefined ;
568
547
569
- if ( parsedItemKey ) {
548
+ if ( parsedItem ) {
570
549
const documentations : string [ ] = [ ] ;
571
550
572
- propInfo = cachedPropInfos . get ( parsedItemKey . prop ) ;
551
+ propInfo = cachedPropInfos . get ( parsedItem . prop ) ;
573
552
if ( propInfo ?. commentMarkdown ) {
574
553
documentations . push ( propInfo . commentMarkdown ) ;
575
554
}
576
555
577
- let { isEvent, propName } = getPropName ( parsedItemKey ) ;
556
+ let { isEvent, propName } = getPropName ( parsedItem ) ;
578
557
if ( isEvent ) {
579
558
// click -> onclick
580
559
propName = 'on' + propName ;
@@ -605,7 +584,7 @@ export function create(
605
584
606
585
// for special props without internal item key
607
586
if ( specialProps . has ( propName ) ) {
608
- parsedItemKey = {
587
+ parsedItem = {
609
588
type : 'componentProp' ,
610
589
tag : '^' ,
611
590
prop : propName ,
@@ -640,12 +619,12 @@ export function create(
640
619
item . kind = 6 satisfies typeof vscode . CompletionItemKind . Variable ;
641
620
tokens . push ( '\u0000' ) ;
642
621
}
643
- else if ( parsedItemKey ) {
622
+ else if ( parsedItem ) {
644
623
645
- const isComponent = parsedItemKey . tag !== '*' ;
646
- const { isEvent, propName } = getPropName ( parsedItemKey ) ;
624
+ const isComponent = parsedItem . tag !== '*' ;
625
+ const { isEvent, propName } = getPropName ( parsedItem ) ;
647
626
648
- if ( parsedItemKey . type === 'componentProp' ) {
627
+ if ( parsedItem . type === 'componentProp' ) {
649
628
if ( isComponent || specialProps . has ( propName ) ) {
650
629
item . kind = 5 satisfies typeof vscode . CompletionItemKind . Field ;
651
630
}
@@ -796,13 +775,13 @@ function getReplacement(list: html.CompletionList, doc: TextDocument) {
796
775
}
797
776
798
777
function getPropName (
799
- itemKey : ReturnType < typeof parseItemKey > & { }
778
+ parsedItem : ReturnType < typeof parseItemKey > & { }
800
779
) {
801
- const name = hyphenateAttr ( itemKey . prop ) ;
780
+ const name = hyphenateAttr ( parsedItem . prop ) ;
802
781
if ( name . startsWith ( 'on-' ) ) {
803
782
return { isEvent : true , propName : name . slice ( 'on-' . length ) } ;
804
783
}
805
- else if ( itemKey . type === 'componentEvent' ) {
784
+ else if ( parsedItem . type === 'componentEvent' ) {
806
785
return { isEvent : true , propName : name } ;
807
786
}
808
787
return { isEvent : false , propName : name } ;
0 commit comments