diff --git a/README.md b/README.md
index d377be665..c5af8f161 100644
--- a/README.md
+++ b/README.md
@@ -51,31 +51,33 @@ Make sure that you have Node.js
npm install flowbite
```
-2. Require Flowbite as a plugin inside the `tailwind.config.js` file:
+2. Use the Flowbite CLI and run the following command to set up Flowbite in the `tailwind.config.js` file:
-```javascript
-module.exports = {
-
- plugins: [
- require('flowbite/plugin')
- ]
-
-}
+```bash
+npx flowbite init
```
-3. Make sure that you add the template path to the `tailwind.config.js` file:
+This will either generate a new default Tailwnd configuration file with Flowbite installed or set up Flowbite inside an existing Tailwind CSS project:
```javascript
module.exports = {
- content: [
- "./node_modules/flowbite/**/*.js"
- ]
+ // other options ...
+
+ content: [
+ // other templates paths...
+ "./node_modules/flowbite/**/*.js"
+ ]
+
+ plugins: [
+ // other plugins...
+ require('flowbite/plugin')
+ ],
}
```
-4. Include the main JavaScript file to make interactive elements work:
+3. Include the main JavaScript file to make interactive elements work:
```html
diff --git a/cli.js b/cli.js
new file mode 100644
index 000000000..676d9b815
--- /dev/null
+++ b/cli.js
@@ -0,0 +1,210 @@
+#! /usr/bin/env node
+/* eslint-disable @typescript-eslint/no-var-requires */
+// Check if --debug is passed
+const debug = process.argv.includes('--debug');
+const fs = require('fs');
+
+if (
+ process.argv.includes('-h') ||
+ process.argv.includes('--help') ||
+ process.argv.length == 2
+) {
+ if (process.argv.includes('init')) {
+ console.log(
+ '\x1b[0;34mFlowbite CLI \x1b[0m\n\nUsage:\nflowbite init [options]\n\nOptions:\n -h, --help\t\tShow this help\n -d, --default\t\tCreates a default tailwind.config.js without Flowbite installed\n -p --postcss\t\tInitialize a postcss.config.js file\n --debug\t\tShow debug messages'
+ );
+ process.exit(1);
+ } else {
+ console.log(
+ '\x1b[0;34mFlowbite CLI \x1b[0m\n\nUsage:\nflowbite init [options]\n\nOptions:\n -h, --help\t\tShow this help\n -d, --default\t\tCreates a default tailwind.config.js without Flowbite installed\n -p --postcss\t\tInitialize a postcss.config.js file\n --debug\t\tShow debug messages'
+ );
+ process.exit(1);
+ }
+}
+
+if (process.argv.includes('-v') || process.argv.includes('--version')) {
+ console.log(
+ '\x1b[0;34mFlowbite v' + require('./package.json').version + '\x1b[0m'
+ );
+ process.exit(1);
+}
+
+if (process.argv.includes('init')) {
+ init();
+} else {
+ console.log(
+ '\x1b[0;34m Flowbite CLI \x1b[0m\n\nUsage:\n\n flowbite init [options]\n\nOptions:\n -h, --help\t\tShow this help\n -v, --version\t\tShow the version\n --debug\t\tShow debug messages'
+ );
+ process.exit(1);
+}
+
+async function createTailwindConfig() {
+ if (fs.existsSync('tailwind.config.js')) {
+ log('tailwind.config.js already exists.');
+ return;
+ }
+ const data = `module.exports = {
+ content: [],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
+};
+`;
+
+ // Write the file
+ fs.writeFileSync('tailwind.config.js', data, 'utf8');
+ log('tailwind.config.js created.');
+}
+
+async function updateTailwindConfig() {
+ // Read the file and replace plugins:[ with plugins: [require("flowbite")
+ var data = fs.readFileSync('tailwind.config.js', 'utf8');
+ var config;
+ try {
+ // Try to read the config file
+ config = await require('./tailwind.config.js');
+ } catch (e) {
+ log('Error: Invalid tailwind.config.js file.', true);
+ process.exit(1);
+ }
+ // Check if the plugin is already added
+ if (
+ data.includes("require('flowbite/plugin')") &&
+ data.includes('./node_modules/flowbite/**/*.js')
+ ) {
+ log('Flowbite has already been installed in tailwind.config.js.', true);
+ process.exit(1);
+ }
+
+ // Check if flowbite is installed
+ if (!fs.existsSync('node_modules/flowbite')) {
+ log(
+ 'Flowbite is not installed.\nInstall it with \x1b[1m\x1b[4mnpm install flowbite\x1b[0m.',
+ true
+ );
+ }
+ // Use regular expressions to find the line where the plugins are defined
+ const pluginLine = data.match(/plugins: \[[\s\S]*\]/)[0];
+
+ // Use regular expressions to find the current plugins
+ var currentPlugins = pluginLine?.match(/require\('.*'\)/g);
+
+ // Checks if the plugin is already added
+ if (pluginLine) {
+ if (!currentPlugins) currentPlugins = [];
+ if (currentPlugins.includes("require('flowbite/plugin')"))
+ return log(
+ 'Flowbite has already been installed in tailwind.config.js.'
+ );
+ // Add the new plugin to the current plugins
+ currentPlugins.push("require('flowbite/plugin')");
+
+ log('Flowbite plugin added to tailwind.config.js.');
+ }
+
+ // Check if the content is already added
+ if (!config.content.includes('./node_modules/flowbite/**/*.js')) {
+ config.content.push('./node_modules/flowbite/**/*.js');
+ log('Flowbite node_modules added to tailwind.config.js.');
+ }
+
+ // Updates the file
+ var result = data.replace(
+ /plugins\s*:\s*\[(.*)]/gs,
+ 'plugins: [' + currentPlugins.join(', ') + ']'
+ );
+
+ // Add " to all the content paths
+ var content = config.content.map((path, index) => {
+ // Check if index is the last one
+ if (index === config.content.length - 1)
+ return "\n '" + path + "'\n ";
+ return "\n '" + path + "'";
+ });
+ result = result.replace(
+ /content\s*:\s*\[(.*?)]/gs,
+ 'content: [' + content.join(',') + ']'
+ );
+
+ // Write the file
+ fs.writeFileSync('tailwind.config.js', result, 'utf8');
+ log('tailwind.config.js updated.');
+}
+
+async function postCss() {
+ // Check if postcss.config.js exists
+ if (!fs.existsSync('postcss.config.js')) {
+ if (
+ !fs.existsSync('node_modules/postcss') &&
+ !fs.existsSync('node_modules/tailwindcss') &&
+ !fs.existsSync('node_modules/autoprefixer')
+ ) {
+ log(
+ "PostCSS and AutoPrefixer aren't installed.\nInstall them with \x1b[1m\x1b[4mnpm install -D tailwindcss postcss autoprefixer\x1b[0m.",
+ true
+ );
+ }
+ // Create postcss.config.js
+ const data = `module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
+`;
+ fs.writeFileSync('postcss.config.js', data, 'utf8');
+ log('postcss.config.js created.');
+ } else {
+ return;
+ }
+}
+
+/**
+ *
+ * @param {string} msg
+ * @param {boolean} important
+ * @returns
+ */
+function log(msg, important = false) {
+ if (important == true) {
+ console.log(msg + '\x1b[0m');
+ } else if (debug == true) {
+ console.log(msg + '\x1b[0m');
+ }
+}
+
+/**
+ * Init the tailwind config
+ * @returns
+ */
+async function init() {
+ if (process.argv.includes('-d') || process.argv.includes('--default')) {
+ if (fs.existsSync('tailwind.config.js')) {
+ log('tailwind.config.js already exists.', true);
+ process.exit(1);
+ }
+ await createTailwindConfig();
+ log('Tailwind config created without Flowbite', true);
+ if (process.argv.includes('-p') || process.argv.includes('--postcss')) {
+ await postCss();
+ }
+ process.exit(1);
+ }
+ if (fs.existsSync('tailwind.config.js')) {
+ await updateTailwindConfig();
+ log('Flowbite has been installed in tailwind.config.js.', true);
+ } else {
+ await createTailwindConfig();
+ await updateTailwindConfig();
+ log(
+ 'Created new tailwind.config.js file with Flowbite installed.',
+ true
+ );
+ }
+ if (process.argv.includes('-p') || process.argv.includes('--postcss')) {
+ await postCss();
+ log('Created postcss.config.js file.', true);
+ }
+ process.exit(1);
+}
diff --git a/content/getting-started/introduction.md b/content/getting-started/introduction.md
index bac9cc27c..c911d1bce 100644
--- a/content/getting-started/introduction.md
+++ b/content/getting-started/introduction.md
@@ -61,34 +61,36 @@ Flowbite is technically a plugin that can be included into any existing Tailwind
npm install flowbite
```
-2. Include Flowbite as a plugin inside the `tailwind.config.js` file:
+2. Use the Flowbite CLI and run the following command to set up Flowbite in the `tailwind.config.js` file:
-```javascript
-module.exports = {
-
- plugins: [
- require('flowbite/plugin')
- ]
-
-}
+```bash
+npx flowbite init
```
-3. Additionally to your own `content` data you should add `flowbite` to apply the classes from the interactive elements in the `tailwind.config.js` file:
+This will either generate a new default Tailwnd configuration file with Flowbite installed or set up Flowbite inside an existing Tailwind CSS project:
```javascript
module.exports = {
- content: [
- "./node_modules/flowbite/**/*.js"
- ]
+ // other options ...
+
+ content: [
+ // other templates paths...
+ "./node_modules/flowbite/**/*.js"
+ ]
+
+ plugins: [
+ // other plugins...
+ require('flowbite/plugin')
+ ],
}
```
-4. Require the JavaScript code that powers the interactive elements before the end of your `` tag:
+3. Include the main JavaScript file to make interactive elements work:
```html
-
+
```
### Include via CDN
diff --git a/content/getting-started/quickstart.md b/content/getting-started/quickstart.md
index 36a57a9a2..d14a2aab9 100644
--- a/content/getting-started/quickstart.md
+++ b/content/getting-started/quickstart.md
@@ -27,34 +27,36 @@ Make sure that you have Node.js<
npm install flowbite
```
-2. Require Flowbite as a plugin inside the `tailwind.config.js` file:
+2. Use the Flowbite CLI and run the following command to set up Flowbite in the `tailwind.config.js` file:
-```javascript
-module.exports = {
-
- plugins: [
- require('flowbite/plugin')
- ]
-
-}
+```bash
+npx flowbite init
```
-3. Additionally to your own `content` data you should add `flowbite` to apply the classes from the interactive elements in the `tailwind.config.js` file:
+This will either generate a new default Tailwnd configuration file with Flowbite installed or set up Flowbite inside an existing Tailwind CSS project:
```javascript
module.exports = {
- content: [
- "./node_modules/flowbite/**/*.js"
- ]
+ // other options ...
+
+ content: [
+ // other templates paths...
+ "./node_modules/flowbite/**/*.js"
+ ]
+
+ plugins: [
+ // other plugins...
+ require('flowbite/plugin')
+ ],
}
```
-4. Require the JavaScript code that powers the interactive elements before the end of your `` tag:
+3. Include the main JavaScript file to make interactive elements work:
```html
-
+
```
### Include via CDN
diff --git a/package-lock.json b/package-lock.json
index 237bd0097..8f9418f3b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,6 +12,9 @@
"@popperjs/core": "^2.9.3",
"mini-svg-data-uri": "^1.4.3"
},
+ "bin": {
+ "flowbite": "cli.js"
+ },
"devDependencies": {
"@babel/core": "^7.14.8",
"@babel/preset-env": "^7.14.8",
@@ -20,6 +23,7 @@
"@typescript-eslint/parser": "^5.46.1",
"autoprefixer": "^10.3.3",
"babel-loader": "^8.2.2",
+ "child_process": "^1.0.2",
"copyfiles": "^2.4.1",
"core-js": "^3.8.1",
"css-loader": "^5.2.7",
@@ -3323,6 +3327,12 @@
"node": ">=4"
}
},
+ "node_modules/child_process": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz",
+ "integrity": "sha512-Wmza/JzL0SiWz7kl6MhIKT5ceIlnFPJX+lwUGj7Clhy5MMldsSoJR0+uvRzOS5Kv45Mq7t1PoE8TsOA9bzvb6g==",
+ "dev": true
+ },
"node_modules/chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
@@ -7191,9 +7201,9 @@
"dev": true
},
"node_modules/json5": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
- "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true,
"bin": {
"json5": "lib/cli.js"
@@ -15860,8 +15870,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz",
"integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"@webpack-cli/info": {
"version": "1.5.0",
@@ -15876,8 +15885,7 @@
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz",
"integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"@xtuc/ieee754": {
"version": "1.2.0",
@@ -15917,15 +15925,13 @@
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
"integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"acorn-jsx": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"acorn-node": {
"version": "1.8.2",
@@ -15968,8 +15974,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
"integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"ajv-formats": {
"version": "2.1.1",
@@ -16004,8 +16009,7 @@
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"algoliasearch": {
"version": "4.14.2",
@@ -16470,6 +16474,12 @@
"supports-color": "^5.3.0"
}
},
+ "child_process": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz",
+ "integrity": "sha512-Wmza/JzL0SiWz7kl6MhIKT5ceIlnFPJX+lwUGj7Clhy5MMldsSoJR0+uvRzOS5Kv45Mq7t1PoE8TsOA9bzvb6g==",
+ "dev": true
+ },
"chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
@@ -16865,8 +16875,7 @@
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz",
"integrity": "sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"css-has-pseudo": {
"version": "0.10.0",
@@ -17128,8 +17137,7 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz",
"integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"csso": {
"version": "4.2.0",
@@ -17785,8 +17793,7 @@
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.0.0.tgz",
"integrity": "sha512-5EaAVPsIHu+grmm5WKjxUia4yHgRrbkd8I0ffqUSwixCPMVBrbS97UnzlEY/Q7OWo584vgixefM0kJnUfo/VjA==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"eslint-plugin-prettier": {
"version": "4.2.1",
@@ -18927,8 +18934,7 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"ignore": {
"version": "5.2.1",
@@ -19384,9 +19390,9 @@
"dev": true
},
"json5": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
- "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true
},
"jsonfile": {
@@ -20765,29 +20771,25 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz",
"integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"postcss-discard-duplicates": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz",
"integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"postcss-discard-empty": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz",
"integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"postcss-discard-overridden": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz",
"integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"postcss-double-position-gradients": {
"version": "1.0.0",
@@ -21222,8 +21224,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
"integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"postcss-modules-local-by-default": {
"version": "4.0.0",
@@ -21294,8 +21295,7 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz",
"integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"postcss-normalize-display-values": {
"version": "5.1.0",
@@ -21775,8 +21775,7 @@
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.2.1.tgz",
"integrity": "sha512-aIO8IguumORyRsmT+E7JfJ3A9FEoyhqZR7Au7TBOege3VZkgMvHJMkufeYp4zjnDK2iq4ktkvGMNOQR9T8lisQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"pretty-hrtime": {
"version": "1.0.3",
diff --git a/package.json b/package.json
index f5ef48f11..ecc0f6b78 100644
--- a/package.json
+++ b/package.json
@@ -75,6 +75,7 @@
"@typescript-eslint/parser": "^5.46.1",
"autoprefixer": "^10.3.3",
"babel-loader": "^8.2.2",
+ "child_process": "^1.0.2",
"copyfiles": "^2.4.1",
"core-js": "^3.8.1",
"css-loader": "^5.2.7",
@@ -114,6 +115,8 @@
"files": [
"lib",
"dist",
- "plugin.js"
- ]
+ "plugin.js",
+ "cli.js"
+ ],
+ "bin": "cli.js"
}