diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index 719d8a9d17f..96755add3fc 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -15,19 +15,7 @@ "url": "https://github.com/Microsoft/vscode-emmet" }, "activationEvents": [ - "onLanguage:html", - "onLanguage:jade", - "onLanguage:slim", - "onLanguage:haml", - "onLanguage:xml", - "onLanguage:xsl", - "onLanguage:css", - "onLanguage:scss", - "onLanguage:sass", - "onLanguage:less", - "onLanguage:stylus", - "onLanguage:javascriptreact", - "onLanguage:typescriptreact" + "*" ], "main": "./out/extension", "contributes": { diff --git a/extensions/emmet/src/abbreviationActions.ts b/extensions/emmet/src/abbreviationActions.ts index 767e8497d97..43ca6ee681e 100644 --- a/extensions/emmet/src/abbreviationActions.ts +++ b/extensions/emmet/src/abbreviationActions.ts @@ -49,39 +49,51 @@ export function expandAbbreviation() { return; } let syntax = getSyntax(editor.document); - let output = expandAbbreviationHelper(syntax, editor.document, editor.selection); + let mappedSyntax = false; + let emmetConfig = vscode.workspace.getConfiguration('emmet'); + if (emmetConfig && emmetConfig['syntaxProfiles']) { + let syntaxProfiles = emmetConfig['syntaxProfiles']; + if (typeof syntaxProfiles[syntax] === 'string') { + syntax = syntaxProfiles[syntax]; + mappedSyntax = true; + } + } + let output = expandAbbreviationHelper(syntax, editor.document, editor.selection, mappedSyntax); if (output) { - editor.insertSnippet(new vscode.SnippetString(output.expandedText), output.rangeToReplace); + editor.insertSnippet(new vscode.SnippetString(output.expandedText), output.abbreviationRange); } } export interface ExpandAbbreviationHelperOutput { expandedText: string; - rangeToReplace: vscode.Range; + abbreviationRange: vscode.Range; abbreviation: string; syntax: string; } /** * Expands abbreviation at given range in the given document - * @param syntax - * @param document - * @param rangeToReplace - */ -export function expandAbbreviationHelper(syntax: string, document: vscode.TextDocument, rangeToReplace: vscode.Range): ExpandAbbreviationHelperOutput { - let parseContent = isStyleSheet(syntax) ? parseStylesheet : parse; - let rootNode: Node = parseContent(new DocumentStreamReader(document)); - let currentNode = getNode(rootNode, rangeToReplace.end); + * @param syntax string syntax to be used for expanding abbreviations + * @param document vscode.TextDocument + * @param abbreviationRange vscode.Range range of the abbreviation that needs to be expanded + * @param mappedSyntax Boolean Pass true if given document language was mapped to given syntax to get emmet abbreviation expansions. + * */ +export function expandAbbreviationHelper(syntax: string, document: vscode.TextDocument, abbreviationRange: vscode.Range, mappedSyntax: boolean): ExpandAbbreviationHelperOutput { + if (!mappedSyntax) { + let parseContent = isStyleSheet(syntax) ? parseStylesheet : parse; + let rootNode: Node = parseContent(new DocumentStreamReader(document)); + let currentNode = getNode(rootNode, abbreviationRange.end); - if (forceCssSyntax(syntax, currentNode, rangeToReplace.end)) { - syntax = 'css'; - } else if (!isValidLocationForEmmetAbbreviation(currentNode, syntax, rangeToReplace.end)) { - return; + if (forceCssSyntax(syntax, currentNode, abbreviationRange.end)) { + syntax = 'css'; + } else if (!isValidLocationForEmmetAbbreviation(currentNode, syntax, abbreviationRange.end)) { + return; + } } - let abbreviation = document.getText(rangeToReplace); - if (rangeToReplace.isEmpty) { - [rangeToReplace, abbreviation] = extractAbbreviation(document, rangeToReplace.start); + let abbreviation = document.getText(abbreviationRange); + if (abbreviationRange.isEmpty) { + [abbreviationRange, abbreviation] = extractAbbreviation(document, abbreviationRange.start); } let options = { @@ -92,7 +104,7 @@ export function expandAbbreviationHelper(syntax: string, document: vscode.TextDo }; let expandedText = expand(abbreviation, options); - return { expandedText, rangeToReplace, abbreviation, syntax }; + return { expandedText, abbreviationRange, abbreviation, syntax }; } /** diff --git a/extensions/emmet/src/emmetCompletionProvider.ts b/extensions/emmet/src/emmetCompletionProvider.ts index 98e80d16995..3a0a0c35396 100644 --- a/extensions/emmet/src/emmetCompletionProvider.ts +++ b/extensions/emmet/src/emmetCompletionProvider.ts @@ -13,7 +13,12 @@ const field = (index, placeholder) => `\${${index}${placeholder ? ':' + placehol const snippetCompletionsCache = new Map(); export class EmmetCompletionItemProvider implements vscode.CompletionItemProvider { - + private _mappedSyntax = false; + constructor(mappedSyntax?: boolean) { + if (mappedSyntax) { + this._mappedSyntax = true; + } + } public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Thenable { if (!vscode.workspace.getConfiguration('emmet')['useNewEmmet']) { @@ -23,12 +28,12 @@ export class EmmetCompletionItemProvider implements vscode.CompletionItemProvide let syntax = getSyntax(document); let expandedAbbr: vscode.CompletionItem; if (vscode.workspace.getConfiguration('emmet')['showExpandedAbbreviation']) { - let output: ExpandAbbreviationHelperOutput = expandAbbreviationHelper(syntax, document, new vscode.Range(position, position)); + let output: ExpandAbbreviationHelperOutput = expandAbbreviationHelper(syntax, document, new vscode.Range(position, position), this._mappedSyntax); if (output) { expandedAbbr = new vscode.CompletionItem(output.abbreviation); expandedAbbr.insertText = new vscode.SnippetString(output.expandedText); expandedAbbr.documentation = removeTabStops(output.expandedText); - expandedAbbr.range = output.rangeToReplace; + expandedAbbr.range = output.abbreviationRange; expandedAbbr.detail = 'Expand Emmet Abbreviation'; syntax = output.syntax; } diff --git a/extensions/emmet/src/extension.ts b/extensions/emmet/src/extension.ts index da9ce80a275..8222b0eef69 100644 --- a/extensions/emmet/src/extension.ts +++ b/extensions/emmet/src/extension.ts @@ -16,34 +16,39 @@ import { toggleComment } from './toggleComment'; import { fetchEditPoint } from './editPoint'; import { fetchSelectItem } from './selectItem'; -interface ISupportedLanguageMode { - id: string; - triggerCharacters: string[]; -} - -const LANGUAGE_MODES: ISupportedLanguageMode[] = [ - { id: 'html', triggerCharacters: ['!', '.', '}'] }, - { id: 'jade', triggerCharacters: ['!', '.', '}'] }, - { id: 'slim', triggerCharacters: ['!', '.', '}'] }, - { id: 'haml', triggerCharacters: ['!', '.', '}'] }, - { id: 'xml', triggerCharacters: ['.', '}'] }, - { id: 'xsl', triggerCharacters: ['.', '}'] }, - - { id: 'javascriptreact', triggerCharacters: ['.'] }, - { id: 'typescriptreact', triggerCharacters: ['.'] }, - - { id: 'css', triggerCharacters: [':'] }, - { id: 'scss', triggerCharacters: [':'] }, - { id: 'sass', triggerCharacters: [':'] }, - { id: 'less', triggerCharacters: [':'] }, - { id: 'stylus', triggerCharacters: [':'] } -]; +const LANGUAGE_MODES: Object = { + 'html': ['!', '.', '}'], + 'jade': ['!', '.', '}'], + 'slim': ['!', '.', '}'], + 'haml': ['!', '.', '}'], + 'xml': ['.', '}'], + 'xsl': ['.', '}'], + 'javascriptreact': ['.'], + 'typescriptreact': ['.'], + 'css': [':'], + 'scss': [':'], + 'sass': [':'], + 'less': [':'], + 'stylus': [':'] +}; export function activate(context: vscode.ExtensionContext) { let completionProvider = new EmmetCompletionItemProvider(); - for (let language of LANGUAGE_MODES) { - const provider = vscode.languages.registerCompletionItemProvider({ language: language.id }, completionProvider, ...language.triggerCharacters); + Object.keys(LANGUAGE_MODES).forEach(language => { + const provider = vscode.languages.registerCompletionItemProvider(language, completionProvider, ...LANGUAGE_MODES[language]); context.subscriptions.push(provider); + }); + + let completionProviderForMappedSyntax = new EmmetCompletionItemProvider(true); + let emmetConfig = vscode.workspace.getConfiguration('emmet'); + if (emmetConfig && emmetConfig['syntaxProfiles']) { + let syntaxProfiles = emmetConfig['syntaxProfiles']; + Object.keys(syntaxProfiles).forEach(syntax => { + if (typeof syntaxProfiles[syntax] === 'string' && LANGUAGE_MODES[syntaxProfiles[syntax]]) { + const provider = vscode.languages.registerCompletionItemProvider(syntax, completionProviderForMappedSyntax, ...LANGUAGE_MODES[syntaxProfiles[syntax]]); + context.subscriptions.push(provider); + } + }); } context.subscriptions.push(vscode.commands.registerCommand('emmet.wrapWithAbbreviation', () => {