-
Notifications
You must be signed in to change notification settings - Fork 149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
enhance: post form builder settings #1513
base: develop
Are you sure you want to change the base?
Changes from 110 commits
63151b3
787c082
a7c5fe7
d008e8a
c96afbf
065b1fa
6607241
ab3ce2c
3eba5a0
7293f64
fe34c3b
ab36c5c
6a93fc4
dbef1af
ab32ffd
ed4b378
d02c221
bc50028
3b59cbc
4443867
aa1c0d8
aa9f072
21d19c2
87f577d
ac5db7e
3df5eeb
bf99c43
b8db203
9b4437f
35b9fcf
2a1ce0b
ba23a52
56e9a33
e3f9a4f
7ab496b
6710ad9
0363606
cbe19ad
178f8f0
b978ab5
3aaa5de
d626f9b
e5201fc
90c62f9
286a488
f561dd1
6657551
689dd70
b06bc5c
5139424
579dba6
4b65706
ad480f8
879ee1b
ceb6a49
78bcb6a
1617bf1
9090d49
1f2ef53
0d7503d
97ee3e6
15246dd
8feaa95
b688177
877eb34
e4e1bce
66a0cbd
9afb324
ba9490f
d25c9fb
55e1d57
8f061ec
3afd959
e9eb64b
16350f3
d0be557
208553d
7361839
eada9c6
69c6621
584c78e
854c8ab
4e82c44
9095cba
f46f83c
259e856
c341f35
9f80024
f248ead
981f1a2
d916542
003c704
bff9194
2937533
3e0aa6f
3d8c78b
0e468ab
6e6d2a5
a10101d
e1eba28
13f4db4
9b591c7
ff514f3
2e51588
9711274
982af8a
cebe79a
6fa7d51
0d0a593
cbdbfe4
ce6d438
ddcccee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,5 +1,10 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'use strict'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
module.exports = function(grunt) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
module.exports = function( grunt) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const tailwindFileMap = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'admin/form-builder/views/form-builder-v4.1.php': 'admin/form-builder.css', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'admin/form-builder/views/post-form-settings.php': 'admin/form-builder.css', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var formBuilderAssets = require('./admin/form-builder/assets/js/form-builder-assets.js'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var pkg = grunt.file.readJSON('package.json'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -112,7 +117,22 @@ module.exports = function(grunt) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tasks: [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'shell:npm_build' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tailwind: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
files: [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'src/css/**/*.css', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'admin/form-builder/views/*.php', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'admin/form-builder/assets/js/**/*.php', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'admin/form-builder/assets/js/**/*.js', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'includes/Admin/**/*.php', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'wpuf-functions.php', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tasks: ['shell:tailwind:src/css/admin/form-builder.css:assets/css/admin/form-builder.css'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
options: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
spawn: false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Clean up build directory | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -224,6 +244,11 @@ module.exports = function(grunt) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
shell: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
npm_build: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
command: 'npm run build', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tailwind: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
command: function ( input, output ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return `npx tailwindcss -i ${input} -o ${output}`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -241,6 +266,7 @@ module.exports = function(grunt) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
grunt.loadNpmTasks( 'grunt-notify' ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
grunt.loadNpmTasks( 'grunt-wp-readme-to-markdown' ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
grunt.loadNpmTasks( 'grunt-shell' ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
grunt.loadNpmTasks( 'grunt-postcss' ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
grunt.registerTask( 'default', [ 'less', 'concat', 'uglify', 'i18n' ] ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -251,4 +277,28 @@ module.exports = function(grunt) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// build stuff | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
grunt.registerTask( 'release', [ 'less', 'concat', 'uglify', 'i18n', 'readme' ] ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
grunt.registerTask( 'zip', [ 'clean', 'copy', 'compress' ] ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
grunt.event.on('watch', function(action, filepath, target) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (target === 'tailwind') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
grunt.task.run('tailwind'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
grunt.registerTask('tailwind', function() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const done = this.async(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Process each file mapping | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Object.entries(tailwindFileMap).forEach(([phpFile, cssFile]) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const inputFile = `src/css/${cssFile}`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const outputFile = `assets/css/${cssFile}`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Ensure the input file exists | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (grunt.file.exists(inputFile)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Run the tailwind command | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
grunt.task.run(`shell:tailwind:${inputFile}:${outputFile}`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
done(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+287
to
+303
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling to the tailwind task. The tailwind task lacks error handling for file operations and shell command execution. grunt.registerTask('tailwind', function() {
const done = this.async();
+ let hasErrors = false;
// Process each file mapping
Object.entries(tailwindFileMap).forEach(([phpFile, cssFile]) => {
const inputFile = `src/css/${cssFile}`;
const outputFile = `assets/css/${cssFile}`;
// Ensure the input file exists
- if (grunt.file.exists(inputFile)) {
+ try {
+ if (!grunt.file.exists(inputFile)) {
+ grunt.log.error(`Input file ${inputFile} does not exist`);
+ hasErrors = true;
+ return;
+ }
+ // Ensure the output directory exists
+ const outputDir = require('path').dirname(outputFile);
+ if (!grunt.file.exists(outputDir)) {
+ grunt.file.mkdir(outputDir);
+ }
// Run the tailwind command
grunt.task.run(`shell:tailwind:${inputFile}:${outputFile}`);
+ } catch (error) {
+ grunt.log.error(`Error processing ${inputFile}: ${error.message}`);
+ hasErrors = true;
+ }
});
- done();
+ done(!hasErrors);
}); 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,179 @@ | ||||||
Vue.component('builder-stage-v4-1', { | ||||||
template: '#tmpl-wpuf-builder-stage-v4-1', | ||||||
|
||||||
mixins: wpuf_form_builder_mixins(wpuf_mixins.builder_stage).concat(wpuf_mixins.add_form_field), | ||||||
|
||||||
computed: { | ||||||
form_fields: function () { | ||||||
return this.$store.state.form_fields; | ||||||
}, | ||||||
|
||||||
field_settings: function () { | ||||||
return this.$store.state.field_settings; | ||||||
}, | ||||||
|
||||||
hidden_fields: function () { | ||||||
return this.$store.state.form_fields.filter(function (item) { | ||||||
return 'custom_hidden_field' === item.template; | ||||||
}); | ||||||
}, | ||||||
|
||||||
editing_form_id: function () { | ||||||
return this.$store.state.editing_field_id; | ||||||
}, | ||||||
}, | ||||||
|
||||||
mounted: function () { | ||||||
var self = this, | ||||||
in_column_field = false; | ||||||
|
||||||
// bind jquery ui sortable | ||||||
$('#form-preview-stage, #form-preview-stage .wpuf-form.sortable-list').sortable({ | ||||||
placeholder: 'form-preview-stage-dropzone', | ||||||
items: '.field-items', | ||||||
handle: '.field-buttons .move', | ||||||
scroll: true, | ||||||
over: function() { | ||||||
in_column_field = false; | ||||||
|
||||||
// if the field drop in column field, then stop field rendering in the builder stage | ||||||
$(".wpuf-column-inner-fields" ).on( "drop", function(event) { | ||||||
var targetColumn = event.currentTarget.classList, | ||||||
isColumnExist = $.inArray(".wpuf-column-inner-fields", targetColumn); | ||||||
|
||||||
if ( isColumnExist ) { | ||||||
in_column_field = true; | ||||||
} | ||||||
} ); | ||||||
}, | ||||||
update: function (e, ui) { | ||||||
var item = ui.item[0], | ||||||
data = item.dataset, | ||||||
source = data.source, | ||||||
toIndex = parseInt($(ui.item).index()), | ||||||
payload = { | ||||||
toIndex: toIndex | ||||||
}; | ||||||
|
||||||
if ('panel' === source) { | ||||||
// add new form element | ||||||
self.$store.state.index_to_insert = parseInt(toIndex); | ||||||
|
||||||
if ( ! in_column_field ) { | ||||||
var field_template = ui.item[0].dataset.formField; | ||||||
self.add_form_field(field_template); | ||||||
} | ||||||
|
||||||
// remove button from stage | ||||||
$(this).find('.wpuf-field-button').remove(); | ||||||
|
||||||
} else if ('stage' === source) { | ||||||
payload.fromIndex = parseInt(data.index); | ||||||
|
||||||
self.$store.commit('swap_form_field_elements', payload); | ||||||
} | ||||||
|
||||||
} | ||||||
}); | ||||||
}, | ||||||
|
||||||
methods: { | ||||||
open_field_settings: function(field_id) { | ||||||
this.$store.commit('open_field_settings', field_id); | ||||||
}, | ||||||
|
||||||
clone_field: function(field_id, index) { | ||||||
var payload = { | ||||||
field_id: field_id, | ||||||
index: index, | ||||||
new_id: this.get_random_id() | ||||||
}; | ||||||
|
||||||
// single instance checking | ||||||
var field = _.find(this.$store.state.form_fields, function (item) { | ||||||
return parseInt(item.id) === parseInt(payload.field_id); | ||||||
}); | ||||||
|
||||||
// check if these are already inserted | ||||||
if ( this.isSingleInstance( field.template ) && this.containsField( field.template ) ) { | ||||||
Swal.fire({ | ||||||
title: "Oops...", | ||||||
text: "You already have this field in the form" | ||||||
}); | ||||||
return; | ||||||
} | ||||||
|
||||||
this.$store.commit('clone_form_field_element', payload); | ||||||
}, | ||||||
|
||||||
delete_field: function(index) { | ||||||
var self = this; | ||||||
|
||||||
(Swal.fire({ | ||||||
text: self.i18n.delete_field_warn_msg, | ||||||
icon: 'warning', | ||||||
showCancelButton: true, | ||||||
confirmButtonColor: '#d54e21', | ||||||
confirmButtonText: self.i18n.yes_delete_it, | ||||||
cancelButtonText: self.i18n.no_cancel_it, | ||||||
customClass: { | ||||||
confirmButton: 'btn btn-success', | ||||||
cancelButton: 'btn btn-danger', | ||||||
} | ||||||
})).then((result) => { | ||||||
if (result.isConfirmed) { | ||||||
self.$store.commit('delete_form_field_element', index); | ||||||
} | ||||||
}); | ||||||
}, | ||||||
|
||||||
delete_hidden_field: function (field_id) { | ||||||
var i = 0; | ||||||
|
||||||
for (i = 0; i < this.form_fields.length; i++) { | ||||||
if (parseInt(field_id) === parseInt(this.form_fields[i].id)) { | ||||||
this.delete_field(i); | ||||||
} | ||||||
} | ||||||
}, | ||||||
|
||||||
is_pro_feature: function (template) { | ||||||
return ( this.field_settings[template] && this.field_settings[template].pro_feature ) ? true : false; | ||||||
}, | ||||||
|
||||||
is_template_available: function (field) { | ||||||
var template = field.template; | ||||||
|
||||||
if (this.field_settings[template]) { | ||||||
if (this.is_pro_preview(template)) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix incorrect method name. The method - if (this.is_pro_preview(template)) {
+ if (this.is_pro_feature(template)) { 📝 Committable suggestion
Suggested change
|
||||||
return false; | ||||||
} | ||||||
|
||||||
return true; | ||||||
} | ||||||
|
||||||
// for example see 'mixin_builder_stage' mixin's 'is_taxonomy_template_available' method | ||||||
if (_.isFunction(this['is_' + template + '_template_available'])) { | ||||||
return this['is_' + template + '_template_available'].call(this, field); | ||||||
} | ||||||
|
||||||
return false; | ||||||
}, | ||||||
|
||||||
is_full_width: function (template) { | ||||||
if (this.field_settings[template] && this.field_settings[template].is_full_width) { | ||||||
return true; | ||||||
} | ||||||
|
||||||
return false; | ||||||
}, | ||||||
|
||||||
is_invisible: function (field) { | ||||||
return ( field.recaptcha_type && 'invisible_recaptcha' === field.recaptcha_type ) ? true : false; | ||||||
}, | ||||||
|
||||||
get_field_name: function (template) { | ||||||
return this.field_settings[template].title; | ||||||
} | ||||||
} | ||||||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add validation for Tailwind CLI input and output paths.
The current implementation doesn't validate the input and output paths before executing the Tailwind CLI command. This could lead to errors if the paths contain spaces or special characters.
📝 Committable suggestion