diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index 263bb63ed63..5085e13b2b6 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -310,7 +310,7 @@ "compile": "gulp compile-extension:emmet" }, "devDependencies": { - "@types/node": "7.0.43", + "@types/node": "8.0.33", "vscode": "1.0.1" }, "dependencies": { diff --git a/extensions/emmet/src/abbreviationActions.ts b/extensions/emmet/src/abbreviationActions.ts index 09c531ed726..ee0e1b5a3be 100644 --- a/extensions/emmet/src/abbreviationActions.ts +++ b/extensions/emmet/src/abbreviationActions.ts @@ -8,6 +8,7 @@ import { Node, HtmlNode, Rule, Property } from 'EmmetNode'; import { getEmmetHelper, getNode, getInnerRange, getMappingForIncludedLanguages, parseDocument, validate, getEmmetConfiguration, isStyleSheet, getEmmetMode } from './util'; const trimRegex = /[\u00a0]*[\d|#|\-|\*|\u2022]+\.?/; +const hexColorRegex = /^#\d+$/; interface ExpandAbbreviationInput { syntax: string; @@ -232,17 +233,18 @@ export function isValidLocationForEmmetAbbreviation(document: vscode.TextDocumen // Fix for https://github.com/Microsoft/vscode/issues/34162 // Other than sass, stylus, we can make use of the terminator tokens to validate position if (syntax !== 'sass' && syntax !== 'stylus' && currentNode.type === 'property') { + const abbreviation = document.getText(new vscode.Range(abbreviationRange.start.line, abbreviationRange.start.character, abbreviationRange.end.line, abbreviationRange.end.character)); const propertyNode = currentNode; if (propertyNode.terminatorToken && propertyNode.separator && position.isAfterOrEqual(propertyNode.separatorToken.end) && position.isBeforeOrEqual(propertyNode.terminatorToken.start)) { - return false; + return hexColorRegex.test(abbreviation); } if (!propertyNode.terminatorToken && propertyNode.separator && position.isAfterOrEqual(propertyNode.separatorToken.end)) { - return false; + return hexColorRegex.test(abbreviation); } } diff --git a/extensions/emmet/src/test/cssAbbreviationAction.test.ts b/extensions/emmet/src/test/cssAbbreviationAction.test.ts index 00b205c682a..5ff9460dad2 100644 --- a/extensions/emmet/src/test/cssAbbreviationAction.test.ts +++ b/extensions/emmet/src/test/cssAbbreviationAction.test.ts @@ -70,7 +70,7 @@ suite('Tests for Expand Abbreviations (CSS)', () => { .foo { margin: a margin: 10px; -} +} `; return withRandomFileEditor(testContent, 'css', (editor, doc) => { @@ -87,6 +87,36 @@ suite('Tests for Expand Abbreviations (CSS)', () => { }); }); + test('Allow hex color when typing property values when there is a property in the next line (CSS)', () => { + const testContent = ` +.foo { + margin: #12 + margin: 10px; +} + `; + + return withRandomFileEditor(testContent, 'css', (editor, doc) => { + editor.selection = new Selection(2, 12, 2, 12); + return expandEmmetAbbreviation(null).then(() => { + assert.equal(editor.document.getText(), testContent.replace('#12', '#121212')); + const cancelSrc = new CancellationTokenSource(); + const completionPromise = completionProvider.provideCompletionItems(editor.document, new Position(2, 12), cancelSrc.token); + if (!completionPromise) { + assert.fail('Completion promise wasnt returned'); + return Promise.resolve(); + } + completionPromise.then(result => { + if (!result || !result.items || !result.items.length) { + assert.fail('Completion promise came back empty'); + return Promise.resolve(); + } + assert.equal(result.items[0].label, '#121212'); + }); + return Promise.resolve(); + }); + }); + }); + test('Skip when typing property values when there is a property in the previous line (CSS)', () => { const testContent = ` .foo { @@ -109,11 +139,41 @@ suite('Tests for Expand Abbreviations (CSS)', () => { }); }); + test('Allow hex color when typing property values when there is a property in the previous line (CSS)', () => { + const testContent = ` +.foo { + margin: 10px; + margin: #12 +} + `; + + return withRandomFileEditor(testContent, 'css', (editor, doc) => { + editor.selection = new Selection(3, 12, 3, 12); + return expandEmmetAbbreviation(null).then(() => { + assert.equal(editor.document.getText(), testContent.replace('#12', '#121212')); + const cancelSrc = new CancellationTokenSource(); + const completionPromise = completionProvider.provideCompletionItems(editor.document, new Position(3, 12), cancelSrc.token); + if (!completionPromise) { + assert.fail('Completion promise wasnt returned'); + return Promise.resolve(); + } + completionPromise.then(result => { + if (!result || !result.items || !result.items.length) { + assert.fail('Completion promise came back empty'); + return Promise.resolve(); + } + assert.equal(result.items[0].label, '#121212'); + }); + return Promise.resolve(); + }); + }); + }); + test('Skip when typing property values when it is the only property in the rule (CSS)', () => { const testContent = ` .foo { margin: a -} +} `; return withRandomFileEditor(testContent, 'css', (editor, doc) => { @@ -130,6 +190,35 @@ suite('Tests for Expand Abbreviations (CSS)', () => { }); }); + test('Allow hex colors when typing property values when it is the only property in the rule (CSS)', () => { + const testContent = ` +.foo { + margin: #12 +} + `; + + return withRandomFileEditor(testContent, 'css', (editor, doc) => { + editor.selection = new Selection(2, 12, 2, 12); + return expandEmmetAbbreviation(null).then(() => { + assert.equal(editor.document.getText(), testContent.replace('#12', '#121212')); + const cancelSrc = new CancellationTokenSource(); + const completionPromise = completionProvider.provideCompletionItems(editor.document, new Position(2, 12), cancelSrc.token); + if (!completionPromise) { + assert.fail('Completion promise wasnt returned'); + return Promise.resolve(); + } + completionPromise.then(result => { + if (!result || !result.items || !result.items.length) { + assert.fail('Completion promise came back empty'); + return Promise.resolve(); + } + assert.equal(result.items[0].label, '#121212'); + }); + return Promise.resolve(); + }); + }); + }); + test('Expand abbreviation in completion list (CSS)', () => { const abbreviation = 'm10'; const expandedText = 'margin: 10px;'; diff --git a/extensions/emmet/yarn.lock b/extensions/emmet/yarn.lock index 95b87244b85..5ba2df336e0 100644 --- a/extensions/emmet/yarn.lock +++ b/extensions/emmet/yarn.lock @@ -35,9 +35,9 @@ version "2.2.0" resolved "https://registry.yarnpkg.com/@emmetio/stream-reader/-/stream-reader-2.2.0.tgz#46cffea119a0a003312a21c2d9b5628cb5fcd442" -"@types/node@7.0.43": - version "7.0.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c" +"@types/node@8.0.33": + version "8.0.33" + resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.33.tgz#1126e94374014e54478092830704f6ea89df04cd" ajv@^5.1.0: version "5.3.0"