import { getLanguageModelCache } from '../languageModelCache' ; import { LanguageService as HTMLLanguageService , HTMLDocument , DocumentContext , FormattingOptions , HTMLFormatConfiguration , SelectionRange } from 'vscode-html-languageservice' ; import { TextDocument , Position , Range , CompletionItem , FoldingRange } from 'vscode-languageserver-types' ; import { LanguageMode , Workspace } from './languageModes' ; import { getPathCompletionParticipant } from './pathCompletion' ; export function getHTMLMode ( htmlLanguageService , workspace ) { let htmlDocuments = getLanguageModelCache < HTMLDocument > ( 10 , 60 , document => htmlLanguageService . parseHTMLDocument ( document ) ) ; return { getId ( ) { return 'html' ; } , getSelectionRanges ( document , positions ) { return htmlLanguageService . getSelectionRanges ( document , positions ) ; } , doComplete ( document , position , settings = workspace . settings ) { let options = settings && settings . html && settings . html . suggest ; let doAutoComplete = settings && settings . html && settings . html . autoClosingTags ; if ( doAutoComplete ) { options . hideAutoCompleteProposals = true ; } let pathCompletionProposals = [ ] ; let participants = [ getPathCompletionParticipant ( document , workspace . folders , pathCompletionProposals ) ] ; htmlLanguageService . setCompletionParticipants ( participants ) ; const htmlDocument = htmlDocuments . get ( document ) ; let completionList = htmlLanguageService . doComplete ( document , position , htmlDocument , options ) ; completionList . items . push ( ... pathCompletionProposals ) ; return completionList ; } , doHover ( document , position ) { return htmlLanguageService . doHover ( document , position , htmlDocuments . get ( document ) ) ; } , findDocumentHighlight ( document , position ) { return htmlLanguageService . findDocumentHighlights ( document , position , htmlDocuments . get ( document ) ) ; } , findDocumentLinks ( document , documentContext ) { return htmlLanguageService . findDocumentLinks ( document , documentContext ) ; } , findDocumentSymbols ( document ) { return htmlLanguageService . findDocumentSymbols ( document , htmlDocuments . get ( document ) ) ; } , format ( document , range , formatParams , settings = workspace . settings ) { let formatSettings = settings && settings . html && settings . html . format ; if ( formatSettings ) { formatSettings = merge ( formatSettings , { } ) ; } else { formatSettings = { } ; } if ( formatSettings . contentUnformatted ) { formatSettings . contentUnformatted = formatSettings . contentUnformatted + ',script' ; } else { formatSettings . contentUnformatted = 'script' ; } formatSettings = merge ( formatParams , formatSettings ) ; return htmlLanguageService . format ( document , range , formatSettings ) ; } , getFoldingRanges ( document ) { return htmlLanguageService . getFoldingRanges ( document ) ; } , doAutoClose ( document , position ) { let offset = document . offsetAt ( position ) ; let text = document . getText ( ) ; if ( offset > 0 && text . charAt ( offset - 1 ) . match ( /[>\/]/g ) ) { return htmlLanguageService . doTagComplete ( document , position , htmlDocuments . get ( document ) ) ; } return null ; } , onDocumentRemoved ( document ) { htmlDocuments . onDocumentRemoved ( document ) ; } , dispose ( ) { htmlDocuments . dispose ( ) ; } } ; } function merge ( src , dst ) { for ( const key in src ) { if ( src . hasOwnProperty ( key ) ) { dst [ key ] = src [ key ] ; } } return dst ; }