From 067ed91b79018ba7b9fcfd5705223262602b78bc Mon Sep 17 00:00:00 2001 From: Ramya Achutha Rao Date: Fri, 14 Sep 2018 10:44:44 -0700 Subject: [PATCH] Allow emmet inside script tag with js mime if js is mapped to html Fixes #58562 --- extensions/emmet/src/abbreviationActions.ts | 15 +++++- .../emmet/src/test/abbreviationAction.test.ts | 51 ++++++++++++++++++- extensions/emmet/src/util.ts | 2 +- 3 files changed, 63 insertions(+), 5 deletions(-) diff --git a/extensions/emmet/src/abbreviationActions.ts b/extensions/emmet/src/abbreviationActions.ts index 707eca045a1..bd2fdd5d1cc 100644 --- a/extensions/emmet/src/abbreviationActions.ts +++ b/extensions/emmet/src/abbreviationActions.ts @@ -5,7 +5,7 @@ import * as vscode from 'vscode'; import { Node, HtmlNode, Rule, Property, Stylesheet } from 'EmmetNode'; -import { getEmmetHelper, getNode, getInnerRange, getMappingForIncludedLanguages, parseDocument, validate, getEmmetConfiguration, isStyleSheet, getEmmetMode, parsePartialStylesheet, isStyleAttribute, getEmbeddedCssNodeIfAny, isTemplateScript } from './util'; +import { getEmmetHelper, getNode, getInnerRange, getMappingForIncludedLanguages, parseDocument, validate, getEmmetConfiguration, isStyleSheet, getEmmetMode, parsePartialStylesheet, isStyleAttribute, getEmbeddedCssNodeIfAny, allowedMimeTypesInScriptTag } from './util'; const trimRegex = /[\u00a0]*[\d|#|\-|\*|\u2022]+\.?/; const hexColorRegex = /^#[\d,a-f,A-F]{0,6}$/; @@ -442,7 +442,18 @@ export function isValidLocationForEmmetAbbreviation(document: vscode.TextDocumen if (currentHtmlNode) { if (currentHtmlNode.name === 'script') { - return isTemplateScript(currentHtmlNode); + const typeAttribute = (currentHtmlNode.attributes || []).filter(x => x.name.toString() === 'type')[0]; + const typeValue = typeAttribute ? typeAttribute.value.toString() : ''; + + if (allowedMimeTypesInScriptTag.indexOf(typeValue) > -1) { + return true; + } + + const isScriptJavascriptType = !typeValue || typeValue === 'application/javascript' || typeValue === 'text/javascript'; + if (isScriptJavascriptType) { + return !!getSyntaxFromArgs({ language: 'javascript' }); + } + return false; } const innerRange = getInnerRange(currentHtmlNode); diff --git a/extensions/emmet/src/test/abbreviationAction.test.ts b/extensions/emmet/src/test/abbreviationAction.test.ts index b5fb87d8b07..af7dbbdba1e 100644 --- a/extensions/emmet/src/test/abbreviationAction.test.ts +++ b/extensions/emmet/src/test/abbreviationAction.test.ts @@ -36,13 +36,14 @@ const htmlContents = ` span.hello `; suite('Tests for Expand Abbreviations (HTML)', () => { const oldValueForExcludeLanguages = workspace.getConfiguration('emmet').inspect('excludeLanguages'); + const oldValueForInlcudeLanguages = workspace.getConfiguration('emmet').inspect('includeLanguages'); teardown(() => { // close all editors return closeAllEditors; @@ -337,7 +338,7 @@ suite('Tests for Expand Abbreviations (HTML)', () => { }); }); - test('Expand html when inside script tag with html type (HTML)', () => { + test('Expand html in completion list when inside script tag with html type (HTML)', () => { const abbreviation = 'span.hello'; const expandedText = ''; @@ -383,6 +384,52 @@ suite('Tests for Expand Abbreviations (HTML)', () => { }); }); + test('Expand html when inside script tag with javascript type if js is mapped to html (HTML)', () => { + return workspace.getConfiguration('emmet').update('includeLanguages', {"javascript": "html"}, ConfigurationTarget.Global).then(() => { + return withRandomFileEditor(htmlContents, 'html', (editor, doc) => { + editor.selection = new Selection(24, 10, 24, 10); + let expandPromise = expandEmmetAbbreviation(null); + if (!expandPromise) { + return Promise.resolve(); + } + return expandPromise.then(() => { + assert.equal(editor.document.getText(), htmlContents.replace('span.bye', '')); + }); + }).then(() => { + return workspace.getConfiguration('emmet').update('includeLanguages', oldValueForInlcudeLanguages || {}, ConfigurationTarget.Global); + }); + }); + }); + + test('Expand html in completion list when inside script tag with javascript type if js is mapped to html (HTML)', () => { + const abbreviation = 'span.bye'; + const expandedText = ''; + return workspace.getConfiguration('emmet').update('includeLanguages', {"javascript": "html"}, ConfigurationTarget.Global).then(() => { + return withRandomFileEditor(htmlContents, 'html', (editor, doc) => { + editor.selection = new Selection(24, 10, 24, 10); + const cancelSrc = new CancellationTokenSource(); + const completionPromise = completionProvider.provideCompletionItems(editor.document, editor.selection.active, cancelSrc.token, { triggerKind: CompletionTriggerKind.Invoke }); + if (!completionPromise) { + assert.equal(1, 2, `Problem with expanding span.bye`); + return Promise.resolve(); + } + + return completionPromise.then((completionList: CompletionList) => { + if (!completionList.items || !completionList.items.length) { + assert.equal(1, 2, `Problem with expanding span.bye`); + return Promise.resolve(); + } + const emmetCompletionItem = completionList.items[0]; + assert.equal(emmetCompletionItem.label, abbreviation, `Label of completion item (${emmetCompletionItem.label}) doesnt match.`); + assert.equal((emmetCompletionItem.documentation || '').replace(/\|/g, ''), expandedText, `Docs of completion item doesnt match.`); + return Promise.resolve(); + }); + }).then(() => { + return workspace.getConfiguration('emmet').update('includeLanguages', oldValueForInlcudeLanguages || {}, ConfigurationTarget.Global); + }); + }); + }); + // test('No expanding when html is excluded in the settings', () => { // return workspace.getConfiguration('emmet').update('excludeLanguages', ['html'], ConfigurationTarget.Global).then(() => { // return testExpandAbbreviation('html', new Selection(9, 6, 9, 6), '', '', true).then(() => { diff --git a/extensions/emmet/src/util.ts b/extensions/emmet/src/util.ts index b51d04d6cec..589759c4300 100644 --- a/extensions/emmet/src/util.ts +++ b/extensions/emmet/src/util.ts @@ -47,7 +47,7 @@ export const LANGUAGE_MODES: any = { 'typescriptreact': ['!', '.', '}', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] }; -const allowedMimeTypesInScriptTag = ['text/html', 'text/plain', 'text/x-template', 'text/template', 'text/ng-template']; +export const allowedMimeTypesInScriptTag = ['text/html', 'text/plain', 'text/x-template', 'text/template', 'text/ng-template']; const emmetModes = ['html', 'pug', 'slim', 'haml', 'xml', 'xsl', 'jsx', 'css', 'scss', 'sass', 'less', 'stylus']; -- GitLab