-
Notifications
You must be signed in to change notification settings - Fork 57
Emmet in typescript styled plugin #33
Changes from 3 commits
3795d77
b985777
e450fb8
25b9da8
bc5a572
23da090
9d2a5b2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
const assert = require('chai').assert; | ||
const createServer = require('../server-fixture'); | ||
const { openMockFile, getFirstResponseOfType } = require('./_helpers'); | ||
|
||
const mockFileName = 'main.ts'; | ||
|
||
describe('Completions', () => { | ||
it('should return emmet property completions for single line string', () => { | ||
const server = createServer(); | ||
openMockFile(server, mockFileName, 'const q = css`m10-20`'); | ||
server.send({ command: 'completions', arguments: { file: mockFileName, offset: 21, line: 1 } }); | ||
|
||
return server.close().then(() => { | ||
const completionsResponse = getFirstResponseOfType('completions', server); | ||
assert.isTrue(completionsResponse.body.some(item => item.name === 'margin: 10px 20px;')); | ||
}); | ||
}); | ||
|
||
|
||
it('should return emmet property completions for multiline string', () => { | ||
const server = createServer(); | ||
openMockFile(server, mockFileName, [ | ||
'const q = css`', | ||
'm10-20', | ||
'`' | ||
].join('\n')); | ||
server.send({ command: 'completions', arguments: { file: mockFileName, offset: 22, line: 1 } }); | ||
|
||
return server.close().then(() => { | ||
const completionsResponse = getFirstResponseOfType('completions', server); | ||
assert.isTrue(completionsResponse.body.some(item => item.name === 'margin: 10px 20px;')); | ||
}); | ||
}); | ||
|
||
it('should return emmet property completions for nested selector', () => { | ||
const server = createServer(); | ||
openMockFile(server, mockFileName, 'const q = css`position: relative; &:hover { m10-20 }`'); | ||
server.send({ command: 'completions', arguments: { file: mockFileName, offset: 51, line: 1 } }); | ||
|
||
return server.close().then(() => { | ||
const completionsResponse = getFirstResponseOfType('completions', server); | ||
assert.isTrue(completionsResponse.body.some(item => item.name === 'margin: 10px 20px;')); | ||
}); | ||
}); | ||
|
||
it('should return emmet completions when placeholder is used as property', () => { | ||
const server = createServer(); | ||
openMockFile(server, mockFileName, 'css`m10-20 ; boarder: 1px solid ${"red"};`'); | ||
server.send({ command: 'completions', arguments: { file: mockFileName, offset: 11, line: 1 } }); | ||
|
||
return server.close().then(() => { | ||
const completionsResponse = getFirstResponseOfType('completions', server); | ||
assert.isTrue(completionsResponse.body.some(item => item.name === 'margin: 10px 20px;')); | ||
}); | ||
}); | ||
|
||
it('should return emmet completions after where placeholder is used as property', () => { | ||
const server = createServer(); | ||
openMockFile(server, mockFileName, 'css`border: 1px solid ${"red"}; m10-20`'); | ||
server.send({ command: 'completions', arguments: { file: mockFileName, offset: 39, line: 1 } }); | ||
|
||
return server.close().then(() => { | ||
const completionsResponse = getFirstResponseOfType('completions', server); | ||
assert.isTrue(completionsResponse.body.some(item => item.name === 'margin: 10px 20px;')); | ||
}); | ||
}); | ||
|
||
it('should return emmet completions between were placeholders are used as properties', () => { | ||
const server = createServer(); | ||
openMockFile(server, mockFileName, 'css`boarder: 1px solid ${"red"}; color: #12; margin: ${20}; `') | ||
server.send({ command: 'completions', arguments: { file: mockFileName, offset: 44, line: 1 } }); | ||
|
||
return server.close().then(() => { | ||
const completionsResponse = getFirstResponseOfType('completions', server); | ||
assert.isTrue(completionsResponse.body.some(item => item.name === '#121212')); | ||
}); | ||
}); | ||
|
||
it('should return emmet completions on tagged template string with placeholder using dotted tag', () => { | ||
const server = createServer(); | ||
openMockFile(server, mockFileName, 'css.x`color: #12 ; boarder: 1px solid ${"red"};`'); | ||
server.send({ command: 'completions', arguments: { file: mockFileName, offset: 17, line: 1 } }); | ||
|
||
return server.close().then(() => { | ||
const completionsResponse = getFirstResponseOfType('completions', server); | ||
assert.isTrue(completionsResponse.success); | ||
assert.isTrue(completionsResponse.body.some(item => item.name === '#121212')); | ||
}); | ||
}); | ||
|
||
it('should return styled emmet completions inside of nested placeholder', () => { | ||
const server = createServer(); | ||
openMockFile(server, mockFileName, 'styled`background: red; ${(() => css`color: #12`)()}`;'); | ||
server.send({ command: 'completions', arguments: { file: mockFileName, offset: 48, line: 1 } }); | ||
|
||
return server.close().then(() => { | ||
const completionsResponse = getFirstResponseOfType('completions', server); | ||
assert.isTrue(completionsResponse.body.some(item => item.name === '#121212')); | ||
}); | ||
}); | ||
|
||
it('should handle emmet completions in multiline value placeholder correctly ', () => { | ||
const server = createServer(); | ||
openMockFile(server, mockFileName, [ | ||
'css`margin: ${', | ||
'0', | ||
"}; color: #12`"].join('\n')); | ||
server.send({ command: 'completions', arguments: { file: mockFileName, offset: 14, line: 3 } }); | ||
|
||
return server.close().then(() => { | ||
const completionsResponse = getFirstResponseOfType('completions', server); | ||
assert.isTrue(completionsResponse.body.some(item => item.name === 'aliceblue')); | ||
}); | ||
}); | ||
|
||
it('should handle emmet completions in multiline rule placeholder correctly ', () => { | ||
const server = createServer(); | ||
openMockFile(server, mockFileName, [ | ||
'css`', | ||
'${', | ||
'css`margin: 0;`', | ||
'}', | ||
'color: #12`'].join('\n')); | ||
server.send({ command: 'completions', arguments: { file: mockFileName, offset: 11, line: 5 } }); | ||
|
||
return server.close().then(() => { | ||
const completionsResponse = getFirstResponseOfType('completions', server); | ||
assert.isTrue(completionsResponse.body.some(item => item.name === '#121212')); | ||
}); | ||
}); | ||
|
||
it('should return emmet completions inside of nested selector xx', () => { | ||
const server = createServer(); | ||
openMockFile(server, mockFileName, [ | ||
'css`', | ||
' color: red;', | ||
' &:hover {', | ||
' color: #12 ', | ||
' }', | ||
'`'].join('\n')); | ||
server.send({ command: 'completions', arguments: { file: mockFileName, line: 4, offset: 19 } }); | ||
|
||
return server.close().then(() => { | ||
const completionsResponse = getFirstResponseOfType('completions', server); | ||
assert.isTrue(completionsResponse.body.some(item => item.name === '#121212')); | ||
}); | ||
}); | ||
}) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ import * as config from './config'; | |
import { TsStyledPluginConfiguration } from './configuration'; | ||
import { TemplateLanguageService, TemplateContext } from 'typescript-template-language-service-decorator'; | ||
import { LanguageServiceLogger } from './logger'; | ||
import { doComplete as emmetDoComplete, getEmmetCompletionParticipants} from 'vscode-emmet-helper'; | ||
|
||
const wrapperPre = ':root{\n'; | ||
|
||
|
@@ -240,13 +241,22 @@ export default class StyledTemplateLanguageService implements TemplateLanguageSe | |
const doc = this.createVirtualDocument(context); | ||
const virtualPosition = this.toVirtualDocPosition(position); | ||
const stylesheet = this.scssLanguageService.parseStylesheet(doc); | ||
const emmetResults: vscode.CompletionList = { | ||
isIncomplete: true, | ||
items: [] | ||
} | ||
this.cssLanguageService.setCompletionParticipants([getEmmetCompletionParticipants(doc, virtualPosition, 'css', {}, emmetResults)]); | ||
const completionsCss = this.cssLanguageService.doComplete(doc, virtualPosition, stylesheet) || emptyCompletionList; | ||
const completionsScss = this.scssLanguageService.doComplete(doc, virtualPosition, stylesheet) || emptyCompletionList; | ||
completionsScss.items = filterScssCompletionItems(completionsScss.items); | ||
const completions: vscode.CompletionList = { | ||
isIncomplete: false, | ||
items: [...completionsCss.items, ...completionsScss.items], | ||
}; | ||
if (emmetResults.items.length) { | ||
completions.items.push(...emmetResults.items); | ||
completions.isIncomplete = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just a heads up: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, it does. For example: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Opened microsoft/TypeScript#21999. I've discussed this problem with TS before but emmet may be the first real use case for it. As we discussed offline, I believe we should be able to take in this PR even without There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed |
||
} | ||
this._completionsCache.updateCached(context, position, completions); | ||
return completions; | ||
} | ||
|
@@ -466,7 +476,10 @@ function translateSeverity( | |
} | ||
|
||
function toDisplayParts( | ||
text: string | undefined | ||
text: string | vscode.MarkupContent | undefined | ||
): ts.SymbolDisplayPart[] { | ||
if (text && typeof text !== 'string') { | ||
return [{text: text.value, kind: 'text'}]; | ||
} | ||
return text ? [{ text, kind: 'text' }] : []; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nit] Use the actual
line
numbers for the tests