Skip to content

Commit

Permalink
Add support for a bunch of file types
Browse files Browse the repository at this point in the history
  • Loading branch information
sidharthachatterjee committed Oct 21, 2018
1 parent 77508a1 commit 850826c
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 57 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ This extension reads config from the currently open project's `tailwind.js` file
## Thanks

- Special thanks to [Adam Wathan](https://github.com/adamwathan) for Tailwind CSS ❤️
- Thanks to [zignd](https://github.com/zignd) for [HTML-CSS-Class-Completion](https://github.com/zignd/HTML-CSS-Class-Completion). Several regexes were borrowed from there
- Thanks to [zignd](https://github.com/zignd) for [HTML-CSS-Class-Completion](https://github.com/zignd/HTML-CSS-Class-Completion). Regexes and and some logic was borrowed from there

## Contributions

Expand Down
98 changes: 42 additions & 56 deletions src/extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,82 +11,68 @@ const _ = require('lodash')

const generateClasses = require('./tailwind')

const fileTypes = require('./filetypes')

let classes
const triggerCharacters = ['"', "'", ' ', '.']

async function activate(context) {
// Use tailwindcss config to generate classes
// Generate classes and set them on activation
classes = await generateClasses()

const fileSystemWatcher = workspace.createFileSystemWatcher('**/tailwind.js')

// Changes to tailwind.js should invalidate above cache
fileSystemWatcher.onDidChange(async () => {
classes = await generateClasses()
})

// This handles the case where the project didn't have tailwind.js
// but was created after VS Code was initialized
fileSystemWatcher.onDidCreate(async () => {
classes = await generateClasses()
})

// If the config is deleted, it is safe to say that the user isn't going to
// use tailwind and we should remove autocomplete suggestions
fileSystemWatcher.onDidDelete(() => {
classes = []
})

const disposableForHtml = languages.registerCompletionItemProvider(
'html',
{
provideCompletionItems: (document, position, token, context) => {
// Get range including all characters in the current line
// till the current position
const range = new Range(new Position(position.line, 0), position)

// Get text in current line
const textInCurrentLine = document.getText(range)

const classesInCurrentLine = textInCurrentLine
.match(/class=["|']([\w- ]*$)/)[1]
.split(' ')

return _.chain(classes)
.difference(classesInCurrentLine)
.map(classItem => {
return new CompletionItem(classItem, CompletionItemKind.Variable)
})
.value()
}
},
...triggerCharacters
)

context.subscriptions.push(fileSystemWatcher, disposableForHtml)

const disposableForJs = languages.registerCompletionItemProvider(
'javascript',
{
provideCompletionItems: (document, position, token, context) => {
// Get range including all characters in the current line
// till the current position
const range = new Range(new Position(position.line, 0), position)

// Get text in current line
const textInCurrentLine = document.getText(range)

const classesInCurrentLine = textInCurrentLine
.match(/className=["|']([\w- ]*$)/)[1]
.split(' ')

return _.chain(classes)
.difference(classesInCurrentLine)
.map(classItem => {
return new CompletionItem(classItem, CompletionItemKind.Variable)
})
.value()
}
},
...triggerCharacters
)

context.subscriptions.push(fileSystemWatcher, disposableForJs)
const disposables = _.flatMap(fileTypes, ({ extension, patterns }) => {
return _.map(patterns, pattern =>
languages.registerCompletionItemProvider(
extension,
{
provideCompletionItems: (document, position) => {
// Get range including all characters in the current line
// till the current position
const range = new Range(new Position(position.line, 0), position)

// Get text in current line
const textInCurrentLine = document.getText(range)

const classesInCurrentLine = textInCurrentLine
.match(pattern.regex)[1]
.split(pattern.splitCharacter)

return _.chain(classes)
.difference(classesInCurrentLine)
.map(classItem => {
return new CompletionItem(
classItem,
CompletionItemKind.Variable
)
})
.value()
}
},
...triggerCharacters
)
)
})

context.subscriptions.push(disposables)
}

function deactivate() {}
Expand Down
76 changes: 76 additions & 0 deletions src/filetypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Borrowed from https://github.com/zignd/HTML-CSS-Class-Completion/blob/master/src/extension.ts

const classRegex = /class=["|']([\w- ]*$)/
const classNameRegex = /className=["|']([\w- ]*$)/
const applyRegex = /@apply ([\.\w- ]*$)/
const emmetRegex = /(?=\.)([\w-\. ]*$)/

const jsPatterns = [
{
regex: classRegex,
splitCharacter: ' '
},
{
regex: classNameRegex,
splitCharacter: ' '
},
{
regex: emmetRegex,
splitCharacter: '.'
}
]

const htmlPatterns = [
{
regex: classRegex,
splitCharacter: ' '
},
{
regex: emmetRegex,
splitCharacter: '.'
}
]

const stylesPatterns = [
{
regex: applyRegex,
splitCharacter: ' '
}
]

const fileTypes = [
{
extension: 'javascript',
patterns: jsPatterns
},
{
extension: 'javascriptreact',
patterns: jsPatterns
},
{
extension: 'typescriptreact',
patterns: jsPatterns
},
{
extension: 'html',
patterns: htmlPatterns
},
{
extension: 'php',
patterns: htmlPatterns
},
{
extension: 'vue',
patterns: htmlPatterns
},
{
extension: 'css',
patterns: stylesPatterns
},
{
extension: 'scss',
patterns: stylesPatterns
}
]

module.exports = fileTypes

0 comments on commit 850826c

Please sign in to comment.