diff --git a/package-lock.json b/package-lock.json
index 39bb0b7..b11fdf5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -286,9 +286,9 @@
"dev": true
},
"@types/node": {
- "version": "10.12.15",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.15.tgz",
- "integrity": "sha512-9kROxduaN98QghwwHmxXO2Xz3MaWf+I1sLVAA6KJDF5xix+IyXVhds0MAfdNwtcpSrzhaTsNB0/jnL86fgUhqA==",
+ "version": "10.12.17",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.17.tgz",
+ "integrity": "sha512-umSCRkjWH70uNzFiOof5yxCqrMXIBJ9UJJUzbEsmtWt8apURQh06pylGMqnhdjHGJSeoBrhzk+mibu6NgL1oBA==",
"dev": true
},
"@types/q": {
@@ -477,13 +477,13 @@
"dev": true
},
"autoprefixer": {
- "version": "9.4.2",
- "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.4.2.tgz",
- "integrity": "sha512-tYQYJvZvqlJCzF+BLC//uAcdT/Yy4ik9bwZRXr/EehUJ/bjjpTthsWTy8dpowdoIE1sLCDf1ch4Eb2cOSzZC9w==",
+ "version": "9.4.3",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.4.3.tgz",
+ "integrity": "sha512-/XSnzDepRkAU//xLcXA/lUWxpsBuw0WiriAHOqnxkuCtzLhaz+fL4it4gp20BQ8n5SyLzK/FOc7A0+u/rti2FQ==",
"dev": true,
"requires": {
- "browserslist": "^4.3.5",
- "caniuse-lite": "^1.0.30000914",
+ "browserslist": "^4.3.6",
+ "caniuse-lite": "^1.0.30000921",
"normalize-range": "^0.1.2",
"num2fraction": "^1.2.2",
"postcss": "^7.0.6",
@@ -856,7 +856,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/color/-/color-3.1.0.tgz",
"integrity": "sha512-CwyopLkuRYO5ei2EpzpIh6LqJMt6Mt+jZhO5VI5f/wJLZriXQE32/SSqzmrh+QB+AZT81Cj8yv+7zwToW8ahZg==",
- "dev": true,
"requires": {
"color-convert": "^1.9.1",
"color-string": "^1.5.2"
@@ -866,7 +865,6 @@
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
"requires": {
"color-name": "1.1.3"
}
@@ -874,14 +872,12 @@
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
- "dev": true
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"color-string": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
"integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
- "dev": true,
"requires": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
@@ -978,9 +974,9 @@
}
},
"core-js": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.0.tgz",
- "integrity": "sha512-kLRC6ncVpuEW/1kwrOXYX6KQASCVtrh1gQr/UiaVgFlf9WE5Vp+lNe5+h3LuMr5PAucWnnEXwH0nQHRH/gpGtw==",
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.1.tgz",
+ "integrity": "sha512-L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg==",
"dev": true
},
"core-util-is": {
@@ -1394,6 +1390,11 @@
"integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==",
"dev": true
},
+ "dlv": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.2.tgz",
+ "integrity": "sha512-xxD4VSH67GbRvSGUrckvha94RD7hjgOH7rqGxiytLpkaeMvixOHFZTGFK6EkIm3T761OVHT8ABHmGkq9gXgu6Q=="
+ },
"dom-serializer": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
@@ -1466,9 +1467,9 @@
}
},
"electron-to-chromium": {
- "version": "1.3.92",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.92.tgz",
- "integrity": "sha512-En051LMzMl3/asMWGZEtU808HOoVWIpmmZx1Ep8N+TT9e7z/X8RcLeBU2kLSNLGQ+5SuKELzMx+MVuTBXk6Q9w==",
+ "version": "1.3.94",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.94.tgz",
+ "integrity": "sha512-miQqXALb6eBD3OetCtg3UM5XTLMwHISux0l6mh14iiV5SE+qvftgOCXT9Vvp53fWaCLET4sfA/SmIMYHXkaNmw==",
"dev": true
},
"emojis-list": {
@@ -1948,9 +1949,9 @@
"dev": true
},
"globrex": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.1.tgz",
- "integrity": "sha512-bqKcPhb+ZtrISivpu6oLmwIyINlPlzueO/BDCdfnzUeu7SYxnHTXmWP7uQI5PnQXc5yGXOscGBEGagloA2hcSw==",
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
+ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
"dev": true
},
"graceful-fs": {
@@ -2605,9 +2606,9 @@
}
},
"js-base64": {
- "version": "2.4.9",
- "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.9.tgz",
- "integrity": "sha512-xcinL3AuDJk7VSzsHgb9DvvIXayBbadtMZ4HFPx8rUszbW1MuNMlwYVC4zzCZ6e1sqZpnNS5ZFYOhXqA39T7LQ==",
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.0.tgz",
+ "integrity": "sha512-wlEBIZ5LP8usDylWbDNhKPEFVFdI5hCHpnVoT/Ysvoi/PRhJENm/Rlh9TvjYB38HFfKZN7OzEbRjmjvLkFw11g==",
"dev": true
},
"js-tokens": {
@@ -2895,9 +2896,9 @@
}
},
"microbundle": {
- "version": "0.8.3",
- "resolved": "https://registry.npmjs.org/microbundle/-/microbundle-0.8.3.tgz",
- "integrity": "sha512-vJHzfwWFG4Q6Oly+gVE4mm/3t+eqtG+VeHaHNo5ev6i00XoMXJJ5RbTg7Rawh4r5ZkltjLEgk4kICk+4WUcj3w==",
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/microbundle/-/microbundle-0.8.4.tgz",
+ "integrity": "sha512-5mBtwzCQPVlPUDDDG26NYyVado9SFcOirmOSVG96zObsKaaqmvaNSSfzFa/+5sb6Gc1T3Ty0o+0RDM/KYnD+9g==",
"dev": true,
"requires": {
"@babel/core": "^7.1.6",
@@ -2906,7 +2907,7 @@
"@babel/polyfill": "^7.0.0",
"asyncro": "^3.0.0",
"autoprefixer": "^9.0.0",
- "babel-plugin-transform-async-to-promises": "^0.8.1",
+ "babel-plugin-transform-async-to-promises": "^0.8.3",
"brotli-size": "^0.0.3",
"camelcase": "^5.0.0",
"chalk": "^2.4.0",
@@ -2921,6 +2922,7 @@
"rollup-plugin-commonjs": "^9.0.0",
"rollup-plugin-es3": "^1.1.0",
"rollup-plugin-flow": "^1.1.1",
+ "rollup-plugin-json": "^3.1.0",
"rollup-plugin-node-resolve": "^3.3.0",
"rollup-plugin-postcss": "^1.6.1",
"rollup-plugin-preserve-shebang": "^0.1.6",
@@ -3115,9 +3117,9 @@
}
},
"node-releases": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.1.tgz",
- "integrity": "sha512-2UXrBr6gvaebo5TNF84C66qyJJ6r0kxBObgZIDX3D3/mt1ADKiHux3NJPWisq0wxvJJdkjECH+9IIKYViKj71Q==",
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.2.tgz",
+ "integrity": "sha512-j1gEV/zX821yxdWp/1vBMN0pSUjuH9oGUdLCb4PfUko6ZW7KdRs3Z+QGGwDUhYtSpQvdVVyLd2V0YvLsmdg5jQ==",
"dev": true,
"requires": {
"semver": "^5.3.0"
@@ -3288,6 +3290,11 @@
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
"dev": true
},
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
+ },
"p-queue": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/p-queue/-/p-queue-2.4.2.tgz",
@@ -3401,9 +3408,9 @@
}
},
"postcss": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz",
- "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==",
+ "version": "7.0.7",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.7.tgz",
+ "integrity": "sha512-HThWSJEPkupqew2fnuQMEI2YcTj/8gMV3n80cMdJsKxfIh5tHf7nM5JigNX6LxVMqo6zkgQNAI88hyFvBk41Pg==",
"dev": true,
"requires": {
"chalk": "^2.4.1",
@@ -4819,12 +4826,12 @@
"dev": true
},
"resolve": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",
- "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz",
+ "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==",
"dev": true,
"requires": {
- "path-parse": "^1.0.5"
+ "path-parse": "^1.0.6"
}
},
"resolve-from": {
@@ -4996,6 +5003,15 @@
}
}
},
+ "rollup-plugin-json": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-3.1.0.tgz",
+ "integrity": "sha512-BlYk5VspvGpjz7lAwArVzBXR60JK+4EKtPkCHouAWg39obk9S61hZYJDBfMK+oitPdoe11i69TlxKlMQNFC/Uw==",
+ "dev": true,
+ "requires": {
+ "rollup-pluginutils": "^2.3.1"
+ }
+ },
"rollup-plugin-node-resolve": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.4.0.tgz",
@@ -6308,6 +6324,15 @@
"jsonfile": "^4.0.0",
"universalify": "^0.1.0"
}
+ },
+ "resolve": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",
+ "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.5"
+ }
}
}
},
@@ -6393,7 +6418,6 @@
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
- "dev": true,
"requires": {
"is-arrayish": "^0.3.1"
},
@@ -6401,8 +6425,7 @@
"is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
- "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
- "dev": true
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
}
}
},
@@ -6730,6 +6753,14 @@
"globrex": "^0.1.1"
}
},
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "requires": {
+ "os-tmpdir": "~1.0.2"
+ }
+ },
"to-absolute-glob": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz",
diff --git a/package.json b/package.json
index 9f46fb4..470c7bf 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
"version": "0.1.16",
"publisher": "bradlc",
"engines": {
- "vscode": "^1.23.0"
+ "vscode": "^1.30.0"
},
"categories": [
"Other"
@@ -39,6 +39,20 @@
"source.css.postcss"
]
}
+ ],
+ "views": {
+ "explorer": [
+ {
+ "id": "tailwindcssConfigExplorer",
+ "name": "Tailwind CSS"
+ }
+ ]
+ },
+ "commands": [
+ {
+ "command": "tailwindcss.goToDefinition",
+ "title": "Go To Definition"
+ }
]
},
"preview": true,
@@ -61,10 +75,13 @@
"url": "https://github.com/bradlc/vscode-tailwindcss.git"
},
"dependencies": {
+ "color": "^3.1.0",
+ "dlv": "^1.1.2",
+ "tmp": "0.0.33",
"vscode-languageclient": "^5.2.1"
},
"devDependencies": {
- "microbundle": "^0.8.3",
+ "microbundle": "^0.8.4",
"vscode": "^1.1.26"
}
}
diff --git a/resources/icons/border_all.svg b/resources/icons/border_all.svg
new file mode 100644
index 0000000..26405e5
--- /dev/null
+++ b/resources/icons/border_all.svg
@@ -0,0 +1 @@
+
diff --git a/resources/icons/devices.svg b/resources/icons/devices.svg
new file mode 100644
index 0000000..c60e541
--- /dev/null
+++ b/resources/icons/devices.svg
@@ -0,0 +1 @@
+
diff --git a/resources/icons/flip_to_front.svg b/resources/icons/flip_to_front.svg
new file mode 100644
index 0000000..3c4358a
--- /dev/null
+++ b/resources/icons/flip_to_front.svg
@@ -0,0 +1 @@
+
diff --git a/resources/icons/format_bold.svg b/resources/icons/format_bold.svg
new file mode 100644
index 0000000..a661435
--- /dev/null
+++ b/resources/icons/format_bold.svg
@@ -0,0 +1 @@
+
diff --git a/resources/icons/format_line_spacing.svg b/resources/icons/format_line_spacing.svg
new file mode 100644
index 0000000..d0ff5b1
--- /dev/null
+++ b/resources/icons/format_line_spacing.svg
@@ -0,0 +1 @@
+
diff --git a/resources/icons/format_size.svg b/resources/icons/format_size.svg
new file mode 100644
index 0000000..7cbca42
--- /dev/null
+++ b/resources/icons/format_size.svg
@@ -0,0 +1 @@
+
diff --git a/resources/icons/layers.svg b/resources/icons/layers.svg
new file mode 100644
index 0000000..2866f6c
--- /dev/null
+++ b/resources/icons/layers.svg
@@ -0,0 +1 @@
+
diff --git a/resources/icons/opacity.svg b/resources/icons/opacity.svg
new file mode 100644
index 0000000..2d0253e
--- /dev/null
+++ b/resources/icons/opacity.svg
@@ -0,0 +1 @@
+
diff --git a/resources/icons/padding.svg b/resources/icons/padding.svg
new file mode 100644
index 0000000..c539617
--- /dev/null
+++ b/resources/icons/padding.svg
@@ -0,0 +1,11 @@
+
diff --git a/resources/icons/palette.svg b/resources/icons/palette.svg
new file mode 100644
index 0000000..c1b18fb
--- /dev/null
+++ b/resources/icons/palette.svg
@@ -0,0 +1 @@
+
diff --git a/resources/icons/photo_size_select_large.svg b/resources/icons/photo_size_select_large.svg
new file mode 100644
index 0000000..3c269bb
--- /dev/null
+++ b/resources/icons/photo_size_select_large.svg
@@ -0,0 +1 @@
+
diff --git a/resources/icons/rounded_corner.svg b/resources/icons/rounded_corner.svg
new file mode 100644
index 0000000..31c3f59
--- /dev/null
+++ b/resources/icons/rounded_corner.svg
@@ -0,0 +1 @@
+
diff --git a/resources/icons/select_all.svg b/resources/icons/select_all.svg
new file mode 100644
index 0000000..40e0072
--- /dev/null
+++ b/resources/icons/select_all.svg
@@ -0,0 +1 @@
+
diff --git a/resources/icons/straighten.svg b/resources/icons/straighten.svg
new file mode 100644
index 0000000..ff76d0f
--- /dev/null
+++ b/resources/icons/straighten.svg
@@ -0,0 +1 @@
+
diff --git a/resources/icons/title.svg b/resources/icons/title.svg
new file mode 100644
index 0000000..2fae722
--- /dev/null
+++ b/resources/icons/title.svg
@@ -0,0 +1 @@
+
diff --git a/resources/icons/tracking.svg b/resources/icons/tracking.svg
new file mode 100644
index 0000000..d75b8e3
--- /dev/null
+++ b/resources/icons/tracking.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/extension.ts b/src/extension.ts
index 1d3abec..9429c41 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -7,9 +7,14 @@ import {
window as Window,
ExtensionContext,
TextDocument,
+ TextEditor,
OutputChannel,
WorkspaceFolder,
- Uri
+ Uri,
+ commands,
+ Selection,
+ Position,
+ Range
} from 'vscode'
import {
@@ -18,6 +23,10 @@ import {
TransportKind
} from 'vscode-languageclient'
+import { createTreeView } from './treeView'
+
+const CONFIG_GLOB =
+ '**/{tailwind,tailwind.config,tailwind-config,.tailwindrc}.js'
let LANGUAGES: string[] = ['html']
let defaultClient: LanguageClient
@@ -60,13 +69,34 @@ function getOuterMostWorkspaceFolder(folder: WorkspaceFolder): WorkspaceFolder {
return folder
}
-export function activate(context: ExtensionContext) {
+export async function activate(context: ExtensionContext) {
// let module = context.asAbsolutePath(path.join('server', 'out', 'server.js'))
let module = '/Users/brad/Code/tailwindcss-language-server/dist/index.js'
let outputChannel: OutputChannel = Window.createOutputChannel(
'lsp-multi-server-example'
)
+ let files = await Workspace.findFiles(CONFIG_GLOB, '**/node_modules/**', 1)
+
+ if (!files.length) return
+
+ let configPath = files[0].fsPath
+ delete require.cache[configPath]
+
+ let refresh = createTreeView(configPath)
+ commands.registerCommand('tailwindcss.goToDefinition', () => {
+ // refresh()
+ // Window.showInformationMessage('Hello World!')
+ Workspace.openTextDocument(files[0]).then((doc: TextDocument) => {
+ Window.showTextDocument(doc).then((editor: TextEditor) => {
+ let start = new Position(0, 0)
+ let end = new Position(0, 0)
+ editor.revealRange(new Range(start, end))
+ editor.selection = new Selection(start, end)
+ })
+ })
+ })
+
function didOpenTextDocument(document: TextDocument): void {
if (
document.uri.scheme !== 'file' ||
@@ -109,6 +139,11 @@ export function activate(context: ExtensionContext) {
serverOptions,
clientOptions
)
+ // client.onReady().then(() => {
+ // client.onNotification('tailwind/loaded', () => {
+ // console.log('loaded')
+ // })
+ // })
client.start()
clients.set(folder.uri.toString(), client)
}
diff --git a/src/treeView.ts b/src/treeView.ts
new file mode 100644
index 0000000..6931c6c
--- /dev/null
+++ b/src/treeView.ts
@@ -0,0 +1,219 @@
+import {
+ TreeDataProvider,
+ TreeItem,
+ TreeItemCollapsibleState,
+ window as Window,
+ Command,
+ Event,
+ EventEmitter
+} from 'vscode'
+import { getSvgColorFromValue, createTempFile } from './util'
+import dlv from 'dlv'
+import * as path from 'path'
+
+const ICONS = {
+ colors: 'palette.svg',
+ backgroundColors: 'palette.svg',
+ borderColors: 'palette.svg',
+ textColors: 'palette.svg',
+ svgFill: 'palette.svg',
+ svgStroke: 'palette.svg',
+ screens: 'devices.svg',
+ textSizes: 'format_size.svg',
+ fonts: 'title.svg',
+ fontWeights: 'format_bold.svg',
+ zIndex: 'layers.svg',
+ borderWidths: 'border_all.svg',
+ shadows: 'flip_to_front.svg',
+ borderRadius: 'rounded_corner.svg',
+ width: 'straighten.svg',
+ minWidth: 'straighten.svg',
+ maxWidth: 'straighten.svg',
+ height: 'straighten.svg',
+ minHeight: 'straighten.svg',
+ maxHeight: 'straighten.svg',
+ opacity: 'opacity.svg',
+ leading: 'format_line_spacing.svg',
+ backgroundSize: 'photo_size_select_large.svg',
+ padding: 'padding.svg',
+ margin: 'select_all.svg',
+ negativeMargin: 'select_all.svg',
+ tracking: 'tracking.svg'
+}
+
+function configValueToString(value: any): string {
+ if (Array.isArray(value)) {
+ return value.join(', ')
+ }
+ return value.toString()
+}
+
+function isObject(val: any): boolean {
+ return val != null && typeof val === 'object' && Array.isArray(val) === false
+}
+
+class ConfigItem extends TreeItem {
+ constructor(
+ public label: string,
+ public key: string[],
+ public collapsibleState: TreeItemCollapsibleState,
+ public description?: string,
+ public iconPath?: string,
+ public command?: Command
+ ) {
+ super(label, collapsibleState)
+ this.key = key
+ this.description = description
+ this.iconPath = iconPath
+ }
+}
+
+class TailwindDataProvider implements TreeDataProvider {
+ private _onDidChangeTreeData: EventEmitter = new EventEmitter()
+ readonly onDidChangeTreeData: Event = this
+ ._onDidChangeTreeData.event
+
+ private config: any
+
+ constructor(public configPath: string) {
+ this.config = require(configPath)
+ }
+ public refresh(configPath?: string): void {
+ if (configPath) this.configPath = configPath
+ delete require.cache[this.configPath]
+ this.config = require(this.configPath)
+ this._onDidChangeTreeData.fire()
+ }
+ getTreeItem(element: ConfigItem): ConfigItem {
+ return element
+ }
+ async getChildren(element: ConfigItem): Promise {
+ let command = {
+ command: 'tailwindcss.goToDefinition',
+ title: 'Go To Definition'
+ }
+ if (element) {
+ let item = dlv(this.config, element.key)
+ let children = Object.keys(item).map(key => {
+ let isObj = isObject(item[key])
+ let child = new ConfigItem(
+ key,
+ element.key.concat(key),
+ isObj
+ ? TreeItemCollapsibleState.Collapsed
+ : TreeItemCollapsibleState.None,
+ isObj ? undefined : configValueToString(item[key]),
+ undefined,
+ isObj ? undefined : command
+ )
+ let color = getSvgColorFromValue(item[key])
+
+ if (color) {
+ return createTempFile(
+ ``,
+ { postfix: '.svg' }
+ ).then(iconPath => {
+ child.iconPath = iconPath
+ return child
+ })
+ }
+
+ return child
+ })
+ return Promise.all(children)
+ }
+
+ return Object.keys(this.config)
+ .filter(key => ['modules', 'plugins', 'options'].indexOf(key) === -1)
+ .map(
+ key =>
+ new ConfigItem(
+ key,
+ [key],
+ isObject(this.config[key])
+ ? TreeItemCollapsibleState.Collapsed
+ : TreeItemCollapsibleState.None,
+ isObject(this.config[key])
+ ? undefined
+ : configValueToString(this.config[key]),
+ ICONS[key]
+ ? path.join(
+ __filename,
+ '..',
+ '..',
+ 'resources',
+ 'icons',
+ ICONS[key]
+ )
+ : undefined,
+ isObject(this.config[key]) ? undefined : command
+ )
+ )
+ }
+}
+
+function treeDataProvider1(config): TreeDataProvider {
+ return {
+ getChildren: async (element): Promise => {
+ if (element) {
+ let child = dlv(config, element.label, {})
+ let items = Object.keys(child).map(key => {
+ let color = getSvgColorFromValue(child[key])
+
+ if (color) {
+ return createTempFile(
+ ``,
+ { postfix: '.svg' }
+ ).then(iconPath => ({
+ label: key,
+ description: configValueToString(child[key]),
+ iconPath
+ }))
+ }
+
+ return Promise.resolve({
+ label: key,
+ description: configValueToString(child[key])
+ })
+ })
+ return Promise.all(items)
+ }
+
+ return Object.keys(config)
+ .filter(key => ['modules', 'plugins', 'options'].indexOf(key) === -1)
+ .map(key => ({
+ label: key,
+ collapsibleState: isObject(config[key])
+ ? TreeItemCollapsibleState.Collapsed
+ : TreeItemCollapsibleState.None,
+ description: isObject(config[key])
+ ? undefined
+ : configValueToString(config[key]),
+ iconPath: ICONS[key]
+ ? path.join(
+ __filename,
+ '..',
+ '..',
+ 'resources',
+ 'icons',
+ ICONS[key]
+ )
+ : undefined
+ }))
+ },
+ getTreeItem: (element: TreeItem): TreeItem => {
+ return element
+ }
+ }
+}
+
+export function createTreeView(configPath) {
+ let provider = new TailwindDataProvider(configPath)
+ let view = Window.createTreeView('tailwindcssConfigExplorer', {
+ treeDataProvider: provider,
+ showCollapseAll: true
+ })
+ view.reveal(undefined)
+
+ return () => provider.refresh()
+}
diff --git a/src/util.ts b/src/util.ts
new file mode 100644
index 0000000..5d3f624
--- /dev/null
+++ b/src/util.ts
@@ -0,0 +1,31 @@
+import * as fs from 'fs'
+import Color from 'color'
+import tmp from 'tmp'
+
+export function createTempFile(content: string, options = {}): Promise {
+ return new Promise((resolve, reject) => {
+ tmp.file(options, (err, path) => {
+ if (err) return reject(err)
+ fs.writeFile(path, content, 'utf8', err => {
+ if (err) return reject(err)
+ resolve(path)
+ })
+ })
+ })
+}
+
+export function getSvgColorFromValue(value: string): string {
+ if (typeof value !== 'string') return null
+
+ if (value === 'transparent') {
+ return 'none'
+ }
+
+ try {
+ let parsed = Color(value)
+ if (parsed.valpha === 0) return 'none'
+ return parsed.rgb().string()
+ } catch (err) {
+ return null
+ }
+}