├── .gitignore ├── LICENSE ├── README.md ├── generator ├── index.js └── template │ └── src │ └── assets │ └── tailwind.css ├── index.js ├── logo.png ├── package.json └── prompts.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | yarn.lock 4 | 5 | # Log files 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | 10 | # Editor directories and files 11 | .idea 12 | .vscode 13 | *.suo 14 | *.ntvs* 15 | *.njsproj 16 | *.sln 17 | *.sw* 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Jens Eggerstedt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-cli-plugin-tailwind 2 | [![Tailwind CSS](https://img.shields.io/badge/tailwindcss-^2.0.2-blue)](https://tailwindcss.com/) 3 | [![License](https://img.shields.io/npm/l/vue-cli-plugin-tailwind.svg)](https://github.com/forsartis/vue-cli-plugin-tailwind/blob/master/LICENSE) 4 | 5 | A plugin that adds Tailwind CSS to your vue-cli project. 6 | 7 | ## Getting started 8 | Inside your vue-cli project folder add the plugin via: 9 | ``` 10 | vue add tailwind 11 | ``` 12 | Choose what Tailwind config you want to generate: 13 | * **none** - Won't create a config file. Useful if you already have a config (make sure to configure PurgeCSS). 14 | * **minimal** *(default)* - Will create a minimal `tailwind.config.js` file where you can define your customizations. 15 | * **full** - Will generate a `tailwind.config.js` file containing the entire default configuration. 16 | 17 | See [Tailwinds configuration guide](https://tailwindcss.com/docs/configuration) for more info. 18 | 19 | ## PostCSS Configuration 20 | Tailwind CSS will be added as plugins in your PostCSS config. 21 | ```javascript 22 | // postcss.config.js 23 | module.exports = { 24 | plugins: { 25 | tailwindcss: {}, 26 | autoprefixer: {}, 27 | }, 28 | }; 29 | ``` 30 | ## License 31 | [MIT](https://github.com/forsartis/vue-cli-plugin-tailwind/blob/master/LICENSE) 32 | -------------------------------------------------------------------------------- /generator/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | const filenameTailwind = 'tailwind.config.js'; 4 | 5 | function loadModule(src, filename) { 6 | var Module = module.constructor; 7 | var m = new Module(); 8 | m._compile(src, filename); 9 | return m.exports; 10 | } 11 | 12 | function readPostcssConfig(api) { 13 | const filename = 'postcss.config.js'; 14 | const file = api.generator.files[filename]; 15 | 16 | if (file) { 17 | const filePath = api.resolve(filename); 18 | fs.writeFileSync(filePath, ''); 19 | return loadModule(file, filename); 20 | } 21 | 22 | const config = api.generator.originalPkg.postcss; 23 | if (config) { 24 | const copy = { ...config }; 25 | delete config.plugins; 26 | return copy; 27 | } 28 | 29 | return {}; 30 | } 31 | 32 | function generateConfig(api, option) { 33 | const args = ['init']; 34 | if (option === 'full') { 35 | args.push('--full'); 36 | } 37 | const { spawnSync } = require('child_process'); 38 | const tailwind = api.resolve('./node_modules/.bin/tailwind'); 39 | if (!fs.existsSync(tailwind)) throw new Error(`${tailwind} not found`); 40 | spawnSync(tailwind, args, { 41 | cwd: api.generator.context, 42 | shell: process.platform === 'win32', 43 | }); 44 | } 45 | 46 | function injectContentConfig(api) { 47 | const configPath = api.resolve(filenameTailwind); 48 | const tailwindConfig = fs.readFileSync(configPath, 'utf-8'); 49 | fs.writeFileSync( 50 | configPath, 51 | tailwindConfig.replace( 52 | 'content: []', 53 | "content: ['./public/**/*.html', './src/**/*.{vue,js,ts,jsx,tsx}']", 54 | ), 55 | ); 56 | } 57 | 58 | module.exports = (api, options) => { 59 | const postcss = readPostcssConfig(api); 60 | const configs = { 61 | dependencies: { 62 | autoprefixer: '^10', 63 | postcss: '^8', 64 | tailwindcss: '^3', 65 | }, 66 | postcss: { 67 | plugins: { 68 | tailwindcss: {}, 69 | autoprefixer: {}, 70 | }, 71 | }, 72 | }; 73 | 74 | configs.postcss.plugins = { ...configs.postcss.plugins, ...postcss.plugins }; 75 | 76 | api.extendPackage(configs); 77 | 78 | api.injectImports(api.entryFile, `import './assets/tailwind.css'`); 79 | api.render('./template'); 80 | 81 | if (options.replaceConfig) { 82 | delete api.generator.files[filenameTailwind]; 83 | const configPath = api.resolve(filenameTailwind); 84 | try { 85 | fs.unlinkSync(configPath); 86 | } catch (error) { 87 | throw new Error(error); 88 | } 89 | } 90 | 91 | if (options.initConfig && options.replaceConfig !== false) { 92 | api.onCreateComplete(() => { 93 | generateConfig(api, options.initConfig); 94 | injectContentConfig(api); 95 | }); 96 | } 97 | }; 98 | -------------------------------------------------------------------------------- /generator/template/src/assets/tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | 3 | @tailwind components; 4 | 5 | @tailwind utilities; 6 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = () => {}; 2 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forsartis/vue-cli-plugin-tailwind/a4c338e211061a3b20d5b1d9270e1722361f589a/logo.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-cli-plugin-tailwind", 3 | "version": "3.0.0", 4 | "description": "vue-cli plugin for Tailwind CSS", 5 | "author": "Jens Eggerstedt ", 6 | "license": "MIT", 7 | "bugs": "https://github.com/forsartis/vue-cli-plugin-tailwind/issues", 8 | "homepage": "https://github.com/forsartis/vue-cli-plugin-tailwind#readme", 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/forsartis/vue-cli-plugin-tailwind" 12 | }, 13 | "keywords": [ 14 | "vue", 15 | "cli", 16 | "plugin", 17 | "tailwind", 18 | "purgecss" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /prompts.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | module.exports = [ 4 | { 5 | type: 'list', 6 | name: 'initConfig', 7 | message: 'Generate tailwind.config.js', 8 | choices: [ 9 | { name: 'none', value: false }, 10 | { name: 'minimal', value: 'minimal' }, 11 | { name: 'full', value: 'full' }, 12 | ], 13 | default: 1, 14 | }, 15 | { 16 | name: 'replaceConfig', 17 | type: 'confirm', 18 | message: 'tailwind.config.js already exists! Do you want to replace it?', 19 | default: false, 20 | when: answers => { 21 | return answers.initConfig && fs.existsSync('./tailwind.config.js'); 22 | }, 23 | }, 24 | ]; 25 | --------------------------------------------------------------------------------