Merge branch 'master' into diagnostics

master
Brad Cornes 2020-06-11 17:41:47 +01:00
commit 1473a4d88c
11 changed files with 337 additions and 19 deletions

37
.vscode/launch.json vendored 100755
View File

@ -0,0 +1,37 @@
{
"version": "0.2.0",
// List of configurations. Add new configurations or edit existing ones.
"configurations": [
{
"type": "extensionHost",
"request": "launch",
"name": "Launch Client",
"runtimeExecutable": "${execPath}",
"args": ["--extensionDevelopmentPath=${workspaceRoot}"],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/dist/extension/**/*.js"],
// "preLaunchTask": "npm: dev"
},
{
"type": "node",
"request": "attach",
"name": "Attach to Server 6011",
"address": "localhost",
"protocol": "inspector",
"port": 6011,
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/dist/server/**/*.js"]
},
{
"type": "node",
"request": "attach",
"name": "Attach to Server 6012",
"address": "localhost",
"protocol": "inspector",
"port": 6012,
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/dist/server/**/*.js"]
}
]
}

29
.vscode/tasks.json vendored 100755
View File

@ -0,0 +1,29 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "build",
"group": "build",
"presentation": {
"panel": "dedicated",
"reveal": "never"
},
"problemMatcher": ["$tsc"]
},
{
"type": "npm",
"script": "dev",
"isBackground": true,
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"panel": "dedicated",
"reveal": "never"
},
"problemMatcher": ["$tsc-watch"]
}
]
}

View File

@ -7,3 +7,4 @@
contributing.md contributing.md
node_modules/** node_modules/**
src/** src/**
tests/**

75
CHANGELOG.md 100644
View File

@ -0,0 +1,75 @@
# Changelog
## 0.3.0
### General
- Added support for string values in Tailwind's `important` option (#96)
- Removed all unnecessary logs (#91)
- Added support for components in addition to utilities (#67)
- Added description to custom variant completion items where possible
- Config parsing errors are now displayed in the VS Code UI
- Class names from `@tailwind base` are now included (by default `@tailwind base` does not include any class names but plugins may contribute them)
- Color swatches can now be displayed for rules with multiple properties and/or colors with variable alpha (#113)
- Added `tailwindCSS.includeLanguages` setting:
```json
{
"tailwindCSS.includeLanguages": {
"plaintext": "html"
}
}
```
This setting allows you to add additional language support. The key of each entry is the new language ID and the value is any one of the extensions built-in languages, depending on how you want the new language to be treated (e.g. `html`, `css`, or `javascript`)
### HTML
- Added built-in support for `liquid`, `aspnetcorerazor`, `mustache`, `HTML (EEx)`, `html-eex`, `gohtml`, `GoHTML`, and `hbs` languages
- Added syntax definition to embedded stylesheets in HTML files
### CSS
- Added built-in support for `sugarss` language
- Added `theme` (and `config`) helper hovers
- Added `@apply` class name hovers
- Added directive completion items with links to documentation
- Added `@tailwind` completion items (`preflight`/`base`, `utilities`, `components`, `screens`) with links to documentation
- Helper completion items that contain the `.` character will now insert square brackets when selected
- `@apply` completion list now excludes class names that are not compatible
- Added CSS syntax highlighting in `.vue` files (#15)
### JS(X)
- Completions now trigger when using backticks (#50, #93):
```js
const App = () => <div className={`_
```
## 0.2.0
- Support for Tailwind v1 via LSP 🎉
- Support for multi-root workspaces
- Support for reason, slim, edge, njk, svelte files (thanks [@nhducit](https://github.com/nhducit), [@wayness](https://github.com/wayness), [@mattwaler](https://github.com/mattwaler), [@guillaumebriday](https://github.com/guillaumebriday))
- Support for non-default Tailwind separators
- Add `@variants` completions
- Better support for dynamic class(Name) values in JSX
- Disables Emmet support by default. This can be enabled via the `tailwindCSS.emmetCompletions` setting
## 0.1.16
- add support for [EEx templates](https://hexdocs.pm/phoenix/templates.html), via [vscode-elixir](https://marketplace.visualstudio.com/items?itemName=mjmcloug.vscode-elixir) thanks [@dhc02](https://github.com/dhc02)
## 0.1.15
- add support for [leaf](https://github.com/vapor/leaf) files (#16)
## 0.1.10
- add syntax definitions for `@apply` and `config()`:
**Before:**
<img src="https://user-images.githubusercontent.com/2615508/44740655-ed02ee80-aaf2-11e8-8d3e-1075e0801fd7.png" alt="Syntax highlighting before update" width="345" />
**After:**
<img src="https://user-images.githubusercontent.com/2615508/44740606-cba20280-aaf2-11e8-92b8-42adbfe54c61.png" alt="Syntax highlighting after update" width="345" />

81
README.md 100644
View File

@ -0,0 +1,81 @@
# Tailwind CSS IntelliSense
> [Tailwind CSS](https://tailwindcss.com/) class name completion for VS Code
**[Get it from the VS Code Marketplace →](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)**
<img src="https://raw.githubusercontent.com/bradlc/vscode-tailwindcss/master/img/html.gif" alt="HTML autocompletion" width="750">
## Requirements
This extension requires:
- a `tailwind.config.js` file to be [present in your project folder](https://github.com/bradlc/vscode-tailwindcss/blob/master/package.json#L38). You can create it with `npx tailwind init`.
- `tailwindcss` to be installed (present in project `node_modules/`)
## Features
Tailwind CSS IntelliSense uses your projects Tailwind installation and configuration to provide suggestions as you type.
It also includes features that improve the overall Tailwind experience, including improved syntax highlighting, and CSS previews.
### HTML (including Vue, JSX, PHP etc.)
- [Class name suggestions, including support for Emmet syntax](#class-name-suggestions-including-support-for-emmet-syntax)
- Suggestions include color previews where applicable, for example for text and background colors
- They also include a preview of the actual CSS for that class name
- [CSS preview when hovering over class names](#css-preview-when-hovering-over-class-names)
### CSS
- [Suggestions when using `@apply` and config helpers](#suggestions-when-using-apply-and-config)
- Suggestions when using the `@screen` directive
- Suggestions when using the `@variants` directive
- [Improves syntax highlighting when using `@apply` and config helpers](#improves-syntax-highlighting-when-using-apply-and-config-helpers)
## Examples
#### Class name suggestions, including support for Emmet syntax
<img src="https://raw.githubusercontent.com/bradlc/vscode-tailwindcss/master/img/html.gif" alt="HTML autocompletion" width="750">
#### CSS preview when hovering over class names
<img src="https://raw.githubusercontent.com/bradlc/vscode-tailwindcss/master/img/html-hover.gif" alt="HTML hover preview" width="750">
#### Suggestions when using `@apply` and config helpers
<img src="https://raw.githubusercontent.com/bradlc/vscode-tailwindcss/master/img/css.gif" alt="CSS autocompletion" width="750">
#### Improves syntax highlighting when using `@apply` and config helpers
Before:
<img src="https://raw.githubusercontent.com/bradlc/vscode-tailwindcss/master/img/css-highlighting-before.png" alt="CSS syntax highlighting before" width="400">
After:
<img src="https://raw.githubusercontent.com/bradlc/vscode-tailwindcss/master/img/css-highlighting-after.png" alt="CSS syntax highlighting after" width="400">
## Settings
### `tailwindCSS.includeLanguages`
This setting allows you to add additional language support. The key of each entry is the new language ID and the value is any one of the extensions built-in languages, depending on how you want the new language to be treated (e.g. `html`, `css`, or `javascript`):
```json
{
"tailwindCSS.includeLanguages": {
"plaintext": "html"
}
}
```
### `tailwindcss.emmetCompletions`
Enable completions when using [Emmet](https://emmet.io/)-style syntax, for example `div.bg-red-500.uppercase`. **Default: `false`**
```json
{
"tailwindCSS.emmetCompletions": true
}
```

14
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "vscode-tailwindcss", "name": "vscode-tailwindcss",
"version": "0.3.0-alpha.2", "version": "0.3.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -4845,9 +4845,9 @@
}, },
"dependencies": { "dependencies": {
"entities": { "entities": {
"version": "2.0.0", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
"integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==",
"dev": true "dev": true
} }
} }
@ -6896,9 +6896,9 @@
} }
}, },
"vsce": { "vsce": {
"version": "1.75.0", "version": "1.76.1",
"resolved": "https://registry.npmjs.org/vsce/-/vsce-1.75.0.tgz", "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.76.1.tgz",
"integrity": "sha512-qyAQTmolxKWc9bV1z0yBTSH4WEIWhDueBJMKB0GUFD6lM4MiaU1zJ9BtzekUORZu094YeNSKz0RmVVuxfqPq0g==", "integrity": "sha512-WNx6JzRywxAOuhVpjmrsI0eHMK0mCA0YKD8u++7sprmhwCHsoQIBpSf0vp6kVMHBmafknr1Z6K7IC5jIjsNL9Q==",
"dev": true, "dev": true,
"requires": { "requires": {
"azure-devops-node-api": "^7.2.0", "azure-devops-node-api": "^7.2.0",

View File

@ -5,10 +5,15 @@
"preview": true, "preview": true,
"author": "Brad Cornes <hello@bradley.dev>", "author": "Brad Cornes <hello@bradley.dev>",
"license": "MIT", "license": "MIT",
"version": "0.3.0-alpha.2", "version": "0.3.0",
"homepage": "https://github.com/bradlc/vscode-tailwindcss",
"bugs": {
"url": "https://github.com/bradlc/vscode-tailwindcss/issues",
"email": "hello@bradley.dev"
},
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/bradlc/" "url": "https://github.com/bradlc/vscode-tailwindcss.git"
}, },
"publisher": "bradlc", "publisher": "bradlc",
"keywords": [ "keywords": [
@ -55,11 +60,12 @@
"tailwindCSS.emmetCompletions": { "tailwindCSS.emmetCompletions": {
"type": "boolean", "type": "boolean",
"default": false, "default": false,
"description": "" "description": "Enable class name completions when using Emmet-style syntax, for example `div.bg-red-500.uppercase`."
}, },
"tailwindCSS.includeLanguages": { "tailwindCSS.includeLanguages": {
"type": "object", "type": "object",
"default": {} "default": {},
"description": "Enable features in languages that are not supported by default. Add a mapping here between the new language and an already supported language.\n E.g.: `{\"plaintext\": \"html\"}`"
} }
} }
} }
@ -106,7 +112,7 @@
"tiny-invariant": "^1.1.0", "tiny-invariant": "^1.1.0",
"tslint": "^5.16.0", "tslint": "^5.16.0",
"typescript": "^3.8.3", "typescript": "^3.8.3",
"vsce": "^1.75.0", "vsce": "^1.76.1",
"vscode-emmet-helper-bundled": "0.0.1", "vscode-emmet-helper-bundled": "0.0.1",
"vscode-languageclient": "^5.2.1", "vscode-languageclient": "^5.2.1",
"vscode-languageserver": "^5.2.1", "vscode-languageserver": "^5.2.1",

View File

@ -17,6 +17,12 @@ export function runPlugin(plugin, params = {}) {
theme: (path, defaultValue) => dlv(config, `theme.${path}`, defaultValue), theme: (path, defaultValue) => dlv(config, `theme.${path}`, defaultValue),
variants: () => [], variants: () => [],
config: (path, defaultValue) => dlv(config, path, defaultValue), config: (path, defaultValue) => dlv(config, path, defaultValue),
corePlugins: (path) => {
if (Array.isArray(config.corePlugins)) {
return config.corePlugins.includes(path)
}
return dlv(config, `corePlugins.${path}`, true)
},
target: (path) => { target: (path) => {
if (typeof config.target === 'string') { if (typeof config.target === 'string') {
return config.target === 'browserslist' return config.target === 'browserslist'

View File

@ -6,6 +6,8 @@ export const DEFAULT_LANGUAGES = [
'edge', 'edge',
'ejs', 'ejs',
'erb', 'erb',
'gohtml',
'GoHTML',
'haml', 'haml',
'handlebars', 'handlebars',
'hbs', 'hbs',

View File

@ -1,10 +1,10 @@
import { TextDocument, Range, Position } from 'vscode-languageserver' import { TextDocument, Range, Position } from 'vscode-languageserver'
import { DocumentClassName, DocumentClassList, State } from './state' import { DocumentClassName, DocumentClassList, State } from './state'
import lineColumn from 'line-column' import lineColumn from 'line-column'
import { isCssContext } from './css' import { isCssContext, isCssDoc } from './css'
import { isHtmlContext } from './html' import { isHtmlContext, isHtmlDoc, isSvelteDoc, isVueDoc } from './html'
import { isWithinRange } from './isWithinRange' import { isWithinRange } from './isWithinRange'
import { isJsContext } from './js' import { isJsContext, isJsDoc } from './js'
import { getClassAttributeLexer } from './lexers' import { getClassAttributeLexer } from './lexers'
export function findAll(re: RegExp, str: string): RegExpMatchArray[] { export function findAll(re: RegExp, str: string): RegExpMatchArray[] {
@ -83,11 +83,13 @@ export function findClassListsInCssRange(
range: { range: {
start: { start: {
line: globalStart.line + start.line, line: globalStart.line + start.line,
character: globalStart.character + start.character, character:
(end.line === 0 ? globalStart.character : 0) + start.character,
}, },
end: { end: {
line: globalStart.line + end.line, line: globalStart.line + end.line,
character: globalStart.character + end.character, character:
(end.line === 0 ? globalStart.character : 0) + end.character,
}, },
}, },
} }
@ -173,11 +175,14 @@ export function findClassListsInHtmlRange(
range: { range: {
start: { start: {
line: range.start.line + start.line, line: range.start.line + start.line,
character: range.start.character + start.character, character:
(end.line === 0 ? range.start.character : 0) +
start.character,
}, },
end: { end: {
line: range.start.line + end.line, line: range.start.line + end.line,
character: range.start.character + end.character, character:
(end.line === 0 ? range.start.character : 0) + end.character,
}, },
}, },
} }
@ -200,6 +205,80 @@ export function findClassListsInRange(
return findClassListsInHtmlRange(doc, range) return findClassListsInHtmlRange(doc, range)
} }
export function findClassListsInDocument(
state: State,
doc: TextDocument
): DocumentClassList[] {
if (isCssDoc(state, doc)) {
return findClassListsInCssRange(doc)
}
if (isVueDoc(doc)) {
let text = doc.getText()
let blocks = findAll(
/<(?<type>template|style|script)\b[^>]*>.*?(<\/\k<type>>|$)/gis,
text
)
let htmlRanges: Range[] = []
let cssRanges: Range[] = []
for (let i = 0; i < blocks.length; i++) {
let range = {
start: indexToPosition(text, blocks[i].index),
end: indexToPosition(text, blocks[i].index + blocks[i][0].length),
}
if (blocks[i].groups.type === 'style') {
cssRanges.push(range)
} else {
htmlRanges.push(range)
}
}
return [].concat.apply(
[],
[
...htmlRanges.map((range) => findClassListsInHtmlRange(doc, range)),
...cssRanges.map((range) => findClassListsInCssRange(doc, range)),
]
)
}
if (isHtmlDoc(state, doc) || isJsDoc(state, doc) || isSvelteDoc(doc)) {
let text = doc.getText()
let styleBlocks = findAll(/<style(?:\s[^>]*>|>).*?(<\/style>|$)/gis, text)
let htmlRanges: Range[] = []
let cssRanges: Range[] = []
let currentIndex = 0
for (let i = 0; i < styleBlocks.length; i++) {
htmlRanges.push({
start: indexToPosition(text, currentIndex),
end: indexToPosition(text, styleBlocks[i].index),
})
cssRanges.push({
start: indexToPosition(text, styleBlocks[i].index),
end: indexToPosition(
text,
styleBlocks[i].index + styleBlocks[i][0].length
),
})
currentIndex = styleBlocks[i].index + styleBlocks[i][0].length
}
htmlRanges.push({
start: indexToPosition(text, currentIndex),
end: indexToPosition(text, text.length),
})
return [].concat.apply(
[],
[
...htmlRanges.map((range) => findClassListsInHtmlRange(doc, range)),
...cssRanges.map((range) => findClassListsInCssRange(doc, range)),
]
)
}
return []
}
function indexToPosition(str: string, index: number): Position { function indexToPosition(str: string, index: number): Position {
const { line, col } = lineColumn(str + '\n', index) const { line, col } = lineColumn(str + '\n', index)
return { line: line - 1, character: col - 1 } return { line: line - 1, character: col - 1 }

View File

@ -8,6 +8,8 @@ export const HTML_LANGUAGES = [
'edge', 'edge',
'ejs', 'ejs',
'erb', 'erb',
'gohtml',
'GoHTML',
'haml', 'haml',
'handlebars', 'handlebars',
'hbs', 'hbs',