diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index 69fc0e88733..f6a6a2f462b 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -73,6 +73,7 @@ "@emmetio/expand-abbreviation": "^0.5.8", "@emmetio/extract-abbreviation": "^0.1.1", "@emmetio/html-matcher": "^0.3.1", - "@emmetio/css-parser": "^0.3.0" + "@emmetio/css-parser": "^0.3.0", + "vscode-emmet-helper":"0.0.6" } } \ No newline at end of file diff --git a/extensions/emmet/src/abbreviationActions.ts b/extensions/emmet/src/abbreviationActions.ts index 7833d9bd5b8..6d38bd66cda 100644 --- a/extensions/emmet/src/abbreviationActions.ts +++ b/extensions/emmet/src/abbreviationActions.ts @@ -9,7 +9,7 @@ import parseStylesheet from '@emmetio/css-parser'; import parse from '@emmetio/html-matcher'; import Node from '@emmetio/node'; import { getSyntax, getNode, getInnerRange } from './util'; -import { getExpandOptions, extractAbbreviation, isStyleSheet } from './vscode-emmet-helper/abbreviationUtil'; +import { getExpandOptions, extractAbbreviation, isStyleSheet } from 'vscode-emmet-helper'; import { DocumentStreamReader } from './bufferStream'; export function wrapWithAbbreviation() { diff --git a/extensions/emmet/src/balance.ts b/extensions/emmet/src/balance.ts index c87f485ec2a..f48568ea701 100644 --- a/extensions/emmet/src/balance.ts +++ b/extensions/emmet/src/balance.ts @@ -7,7 +7,7 @@ import * as vscode from 'vscode'; import parse from '@emmetio/html-matcher'; import Node from '@emmetio/node'; import { DocumentStreamReader } from './bufferStream'; -import { isStyleSheet } from './vscode-emmet-helper/abbreviationUtil'; +import { isStyleSheet } from 'vscode-emmet-helper'; import { getNode } from './util'; export function balanceOut() { diff --git a/extensions/emmet/src/defaultCompletionProvider.ts b/extensions/emmet/src/defaultCompletionProvider.ts index 47cf45f5ff4..cbc57e40f96 100644 --- a/extensions/emmet/src/defaultCompletionProvider.ts +++ b/extensions/emmet/src/defaultCompletionProvider.ts @@ -8,8 +8,7 @@ import parseStylesheet from '@emmetio/css-parser'; import parse from '@emmetio/html-matcher'; import Node from '@emmetio/node'; import { DocumentStreamReader } from './bufferStream'; -import { isStyleSheet } from './vscode-emmet-helper/abbreviationUtil'; -import { EmmetCompletionItemProvider } from './vscode-emmet-helper/emmetCompletionProvider'; +import { EmmetCompletionItemProvider, isStyleSheet } from 'vscode-emmet-helper'; import { isValidLocationForEmmetAbbreviation } from './abbreviationActions'; import { getSyntax, getNode, getInnerRange } from './util'; diff --git a/extensions/emmet/src/extension.ts b/extensions/emmet/src/extension.ts index e300f7264e8..fdd0507cbb3 100644 --- a/extensions/emmet/src/extension.ts +++ b/extensions/emmet/src/extension.ts @@ -16,7 +16,7 @@ import { toggleComment } from './toggleComment'; import { fetchEditPoint } from './editPoint'; import { fetchSelectItem } from './selectItem'; import { LANGUAGE_MODES, getMappedModes } from './util'; -import { updateExtensionsPath } from './vscode-emmet-helper/abbreviationUtil'; +import { updateExtensionsPath } from 'vscode-emmet-helper'; export function activate(context: vscode.ExtensionContext) { let completionProvider = new DefaultCompletionItemProvider(); diff --git a/extensions/emmet/src/mergeLines.ts b/extensions/emmet/src/mergeLines.ts index 7eed3465461..ba26595e829 100644 --- a/extensions/emmet/src/mergeLines.ts +++ b/extensions/emmet/src/mergeLines.ts @@ -7,7 +7,7 @@ import * as vscode from 'vscode'; import parse from '@emmetio/html-matcher'; import Node from '@emmetio/node'; import { DocumentStreamReader } from './bufferStream'; -import { isStyleSheet } from './vscode-emmet-helper/abbreviationUtil'; +import { isStyleSheet } from 'vscode-emmet-helper'; import { getNode } from './util'; export function mergeLines() { diff --git a/extensions/emmet/src/selectItem.ts b/extensions/emmet/src/selectItem.ts index 5b1b80e045e..c242f8e67c3 100644 --- a/extensions/emmet/src/selectItem.ts +++ b/extensions/emmet/src/selectItem.ts @@ -11,7 +11,7 @@ import parseStylesheet from '@emmetio/css-parser'; import parse from '@emmetio/html-matcher'; import Node from '@emmetio/node'; import { DocumentStreamReader } from './bufferStream'; -import { isStyleSheet } from './vscode-emmet-helper/abbreviationUtil'; +import { isStyleSheet } from 'vscode-emmet-helper'; export function fetchSelectItem(direction: string): void { diff --git a/extensions/emmet/src/splitJoinTag.ts b/extensions/emmet/src/splitJoinTag.ts index c20772eb0f5..49c1b676f0b 100644 --- a/extensions/emmet/src/splitJoinTag.ts +++ b/extensions/emmet/src/splitJoinTag.ts @@ -7,7 +7,7 @@ import * as vscode from 'vscode'; import parse from '@emmetio/html-matcher'; import Node from '@emmetio/node'; import { DocumentStreamReader } from './bufferStream'; -import { isStyleSheet } from './vscode-emmet-helper/abbreviationUtil'; +import { isStyleSheet } from 'vscode-emmet-helper'; import { getNode } from './util'; export function splitJoinTag() { diff --git a/extensions/emmet/src/toggleComment.ts b/extensions/emmet/src/toggleComment.ts index 63fa2275b15..4c2c79f866b 100644 --- a/extensions/emmet/src/toggleComment.ts +++ b/extensions/emmet/src/toggleComment.ts @@ -9,7 +9,7 @@ import parse from '@emmetio/html-matcher'; import parseStylesheet from '@emmetio/css-parser'; import Node from '@emmetio/node'; import { DocumentStreamReader } from './bufferStream'; -import { isStyleSheet } from './vscode-emmet-helper/abbreviationUtil'; +import { isStyleSheet } from 'vscode-emmet-helper'; const startCommentStylesheet = '/*'; const endCommentStylesheet = '*/'; diff --git a/extensions/emmet/src/util.ts b/extensions/emmet/src/util.ts index a38d111cc71..ad6c82e7803 100644 --- a/extensions/emmet/src/util.ts +++ b/extensions/emmet/src/util.ts @@ -7,7 +7,7 @@ import * as vscode from 'vscode'; import parse from '@emmetio/html-matcher'; import Node from '@emmetio/node'; import { DocumentStreamReader } from './bufferStream'; -import { isStyleSheet } from './vscode-emmet-helper/abbreviationUtil'; +import { isStyleSheet } from 'vscode-emmet-helper'; export const LANGUAGE_MODES: Object = { 'html': ['!', '.', '}'], diff --git a/extensions/emmet/src/vscode-emmet-helper/abbreviationUtil.ts b/extensions/emmet/src/vscode-emmet-helper/abbreviationUtil.ts deleted file mode 100644 index d5bc3131a0e..00000000000 --- a/extensions/emmet/src/vscode-emmet-helper/abbreviationUtil.ts +++ /dev/null @@ -1,161 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import * as extract from '@emmetio/extract-abbreviation'; -import * as path from 'path'; -import * as fs from 'fs'; - -let variablesFromFile = {}; -let profilesFromFile = {}; -let emmetExtensionsPath = ''; - -const field = (index, placeholder) => `\${${index}${placeholder ? ':' + placeholder : ''}}`; - -export function isStyleSheet(syntax): boolean { - let stylesheetSyntaxes = ['css', 'scss', 'sass', 'less', 'stylus']; - return (stylesheetSyntaxes.indexOf(syntax) > -1); -} - -/** - * Maps and returns syntaxProfiles of previous format to ones compatible with new emmet modules - * @param syntax - */ -export function getProfile(syntax: string): any { - let profilesFromSettings = vscode.workspace.getConfiguration('emmet')['syntaxProfiles'] || {}; - let profilesConfig = Object.assign({}, profilesFromFile, profilesFromSettings); - - let options = profilesConfig[syntax]; - if (!options || typeof options === 'string') { - if (options === 'xhtml') { - return { - selfClosingStyle: 'xhtml' - }; - } - return {}; - } - let newOptions = {}; - for (let key in options) { - switch (key) { - case 'tag_case': - newOptions['tagCase'] = (options[key] === 'lower' || options[key] === 'upper') ? options[key] : ''; - break; - case 'attr_case': - newOptions['attributeCase'] = (options[key] === 'lower' || options[key] === 'upper') ? options[key] : ''; - break; - case 'attr_quotes': - newOptions['attributeQuotes'] = options[key]; - break; - case 'tag_nl': - newOptions['format'] = (options[key] === 'true' || options[key] === 'false') ? options[key] : 'true'; - break; - case 'indent': - newOptions['attrCase'] = (options[key] === 'true' || options[key] === 'false') ? '\t' : options[key]; - break; - case 'inline_break': - newOptions['inlineBreak'] = options[key]; - break; - case 'self_closing_tag': - if (options[key] === true) { - newOptions['selfClosingStyle'] = 'xml'; break; - } - if (options[key] === false) { - newOptions['selfClosingStyle'] = 'html'; break; - } - newOptions['selfClosingStyle'] = options[key]; - break; - default: - newOptions[key] = options[key]; - break; - } - } - return newOptions; -} - -/** - * Returns variables to be used while expanding snippets - */ -export function getVariables(): any { - let variablesFromSettings = vscode.workspace.getConfiguration('emmet')['variables']; - return Object.assign({}, variablesFromFile, variablesFromSettings); -} - -/** - * Updates customizations from snippets.json and syntaxProfiles.json files in the directory configured in emmet.extensionsPath setting - */ -export function updateExtensionsPath() { - let currentEmmetExtensionsPath = vscode.workspace.getConfiguration('emmet')['extensionsPath']; - if (emmetExtensionsPath !== currentEmmetExtensionsPath) { - emmetExtensionsPath = currentEmmetExtensionsPath; - - if (emmetExtensionsPath && emmetExtensionsPath.trim()) { - let dirPath = path.isAbsolute(emmetExtensionsPath) ? emmetExtensionsPath : path.join(vscode.workspace.rootPath, emmetExtensionsPath); - let snippetsPath = path.join(dirPath, 'snippets.json'); - let profilesPath = path.join(dirPath, 'syntaxProfiles.json'); - if (dirExists(dirPath)) { - fs.readFile(snippetsPath, (err, snippetsData) => { - if (err) { - return; - } - try { - let snippetsJson = JSON.parse(snippetsData.toString()); - variablesFromFile = snippetsJson['variables']; - } catch (e) { - - } - }); - fs.readFile(profilesPath, (err, profilesData) => { - if (err) { - return; - } - try { - profilesFromFile = JSON.parse(profilesData.toString()); - } catch (e) { - - } - }); - } - } - } -} - -function dirExists(dirPath: string): boolean { - try { - - return fs.statSync(dirPath).isDirectory(); - } catch (e) { - return false; - } -} - -/** - * Extracts abbreviation from the given position in the given document - */ -export function extractAbbreviation(document: vscode.TextDocument, position: vscode.Position): [vscode.Range, string] { - let currentLine = document.lineAt(position.line).text; - let result = extract(currentLine, position.character, true); - if (!result) { - return [null, '']; - } - - let rangeToReplace = new vscode.Range(position.line, result.location, position.line, result.location + result.abbreviation.length); - return [rangeToReplace, result.abbreviation]; -} - -/** - * Returns options to be used by the expand module - * @param syntax - * @param textToReplace - */ -export function getExpandOptions(syntax: string, textToReplace?: string) { - return { - field: field, - syntax: syntax, - profile: getProfile(syntax), - addons: syntax === 'jsx' ? { 'jsx': true } : null, - variables: getVariables(), - text: textToReplace ? textToReplace : '' - }; -} \ No newline at end of file diff --git a/extensions/emmet/src/vscode-emmet-helper/emmetCompletionProvider.ts b/extensions/emmet/src/vscode-emmet-helper/emmetCompletionProvider.ts deleted file mode 100644 index 03a5999ef5f..00000000000 --- a/extensions/emmet/src/vscode-emmet-helper/emmetCompletionProvider.ts +++ /dev/null @@ -1,118 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - - -import * as vscode from 'vscode'; -import { expand, createSnippetsRegistry } from '@emmetio/expand-abbreviation'; -import { isStyleSheet, extractAbbreviation, getExpandOptions } from './abbreviationUtil'; - -const snippetKeyCache = new Map(); - -export class EmmetCompletionItemProvider implements vscode.CompletionItemProvider { - private _syntax: string; - constructor(syntax: string) { - if (syntax) { - this._syntax = syntax; - } - } - public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Thenable { - - let emmetConfig = vscode.workspace.getConfiguration('emmet'); - if (!emmetConfig['useNewEmmet'] || !emmetConfig['showExpandedAbbreviation']) { - return Promise.resolve(null); - } - - let [abbreviationRange, abbreviation] = extractAbbreviation(document, position); - let expandedText = expand(abbreviation, getExpandOptions(this._syntax)); - - if (!expandedText) { - return; - } - - let expandedAbbr = new vscode.CompletionItem(abbreviation); - expandedAbbr.insertText = new vscode.SnippetString(expandedText); - expandedAbbr.documentation = this.removeTabStops(expandedText); - expandedAbbr.range = abbreviationRange; - expandedAbbr.detail = 'Emmet Abbreviation'; - - // Workaround for the main expanded abbr not appearing before the snippet suggestions - expandedAbbr.sortText = '0' + expandedAbbr.label; - - let completionItems: vscode.CompletionItem[] = expandedAbbr ? [expandedAbbr] : []; - if (!isStyleSheet(this._syntax)) { - let currentWord = this.getCurrentWord(document, position); - let abbreviationSuggestions = this.getAbbreviationSuggestions(this._syntax, currentWord, abbreviation, abbreviationRange); - completionItems = completionItems.concat(abbreviationSuggestions); - } - return Promise.resolve(new vscode.CompletionList(completionItems, true)); - - - } - getAbbreviationSuggestions(syntax: string, prefix: string, abbreviation: string, abbreviationRange: vscode.Range): vscode.CompletionItem[] { - if (!vscode.workspace.getConfiguration('emmet')['showAbbreviationSuggestions'] || !prefix || !abbreviation) { - return []; - } - - if (!snippetKeyCache.has(syntax)) { - let registry = createSnippetsRegistry(syntax); - let snippetKeys: string[] = registry.all({ type: 'string' }).map(snippet => { - return snippet.key; - }); - snippetKeyCache.set(syntax, snippetKeys); - } - - let snippetKeys = snippetKeyCache.get(syntax); - let snippetCompletions = []; - snippetKeys.forEach(snippetKey => { - if (!snippetKey.startsWith(prefix) || snippetKey === prefix) { - return; - } - - let currentAbbr = abbreviation + snippetKey.substr(prefix.length); - let expandedAbbr = expand(currentAbbr, getExpandOptions(syntax)); - - let item = new vscode.CompletionItem(snippetKey); - item.documentation = this.removeTabStops(expandedAbbr); - item.detail = 'Emmet Abbreviation'; - item.insertText = new vscode.SnippetString(expandedAbbr); - item.range = abbreviationRange; - - // Workaround for snippet suggestions items getting filtered out as the complete abbr does not start with snippetKey - item.filterText = abbreviation; - - // Workaround for the main expanded abbr not appearing before the snippet suggestions - item.sortText = '9' + abbreviation; - - snippetCompletions.push(item); - }); - - return snippetCompletions; - - } - - private getCurrentWord(document: vscode.TextDocument, position: vscode.Position): string { - let wordAtPosition = document.getWordRangeAtPosition(position); - let currentWord = ''; - if (wordAtPosition && wordAtPosition.start.character < position.character) { - let word = document.getText(wordAtPosition); - currentWord = word.substr(0, position.character - wordAtPosition.start.character); - } - - return currentWord; - } - - private removeTabStops(expandedWord: string): string { - return expandedWord.replace(/\$\{\d+\}/g, '').replace(/\$\{\d+:([^\}]+)\}/g, '$1'); - } - -} - - - - - - - -