From b1ee4759c53a3a909da047137801fd6aa0681286 Mon Sep 17 00:00:00 2001 From: Brad Cornes Date: Fri, 28 Dec 2018 18:38:12 +0000 Subject: [PATCH] add tree view --- package-lock.json | 115 ++++++---- package.json | 21 +- resources/icons/border_all.svg | 1 + resources/icons/devices.svg | 1 + resources/icons/flip_to_front.svg | 1 + resources/icons/format_bold.svg | 1 + resources/icons/format_line_spacing.svg | 1 + resources/icons/format_size.svg | 1 + resources/icons/layers.svg | 1 + resources/icons/opacity.svg | 1 + resources/icons/padding.svg | 11 + resources/icons/palette.svg | 1 + resources/icons/photo_size_select_large.svg | 1 + resources/icons/rounded_corner.svg | 1 + resources/icons/select_all.svg | 1 + resources/icons/straighten.svg | 1 + resources/icons/title.svg | 1 + resources/icons/tracking.svg | 4 + src/extension.ts | 39 +++- src/treeView.ts | 219 ++++++++++++++++++++ src/util.ts | 31 +++ 21 files changed, 408 insertions(+), 46 deletions(-) create mode 100644 resources/icons/border_all.svg create mode 100644 resources/icons/devices.svg create mode 100644 resources/icons/flip_to_front.svg create mode 100644 resources/icons/format_bold.svg create mode 100644 resources/icons/format_line_spacing.svg create mode 100644 resources/icons/format_size.svg create mode 100644 resources/icons/layers.svg create mode 100644 resources/icons/opacity.svg create mode 100644 resources/icons/padding.svg create mode 100644 resources/icons/palette.svg create mode 100644 resources/icons/photo_size_select_large.svg create mode 100644 resources/icons/rounded_corner.svg create mode 100644 resources/icons/select_all.svg create mode 100644 resources/icons/straighten.svg create mode 100644 resources/icons/title.svg create mode 100644 resources/icons/tracking.svg create mode 100644 src/treeView.ts create mode 100644 src/util.ts 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 + } +}