grunt-sass multiple src/dest on same structure - sass

I'm working on a multi-website project where all the website share the same structure:
-sites
-site1
-css
-scss
-site2
-css
-scss
In my gruntfile.js i have my sass task wrote this way:
sass: {
options: {
sourceMap: true,
outputStyle: 'compressed'
},
pippo: {
files: {
'sites/site1/css/main.css': 'sites/site1/css/sass/main.scss',
'sites/site2/css/main.css': 'sites/site2/css/sass/main.scss',
}
}
}
is it possible to write it in this way?
sass: {
options: {
sourceMap: true,
outputStyle: 'compressed'
},
pippo: {
files: {
'sites/**/css/main.css': 'sites/**/css/sass/main.scss'
}
}
}
I tested it and it is adding a new ** folder when I build it... Any advice?

after a couple of hours I found a working solution, at the very top of the grunt file I added:
module.exports = function(grunt) {
var fs = require('fs');
console.log("Inside the gruntfile");
//create dynamic list of scss file paths
var objDestSource = {
'public/css/main.css': 'public/css/sass/main.scss'
};
fs.readdirSync('sites').forEach(function(folder){
objDestSource['sites/'+folder+'/css/main.css'] = 'sites/'+folder+'/css/sass/main.scss';
});
console.log(objDestSource);
// end scss function
while in the grunt sass task I just changed to:
sass: {
options: {
sourceMap: true,
outputStyle: 'compressed'
},
taskName: {
files: objDestSource
}
}
and the watch task:
watch: {
sass: {
files: [
'public/css/sass/**/*.scss',
'sites/**/css/sass/**/*.scss'
],
tasks: ['sass'],
options: {
spawn: false
}
}
}
This way I can add a new sub-website without have to edit the gruntfile each time!

Related

CKEditor5 v.32 on Laravel 8 / Laravel Mix 6

Does anybody have a working webpack.mix.js config for CKEditor5 32 on Laravel 8 (Laravel Mix 6 and Webpack 5) already? I have been banging my head to the wall for the past 8 hours and still could not manage to make it work.
Here is the console error I receive.
Before, when I was using Laravel Mix 5 and Webpack 4, this config solution seemed to be working.
But now all I get are a bunch of the same errors during npm compilation.
Config's snipped that worked for me
const CKEditorWebpackPlugin = require('#ckeditor/ckeditor5-dev-webpack-plugin');
const CKEditorStyles = require('#ckeditor/ckeditor5-dev-utils').styles;
//Includes SVGs and CSS files from "node_modules/ckeditor5-*" and any other custom directories
const CKEditorRegex = {
svg: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/, //If you have any custom plugins in your project with SVG icons, include their path in this regex as well.
css: /ckeditor5-[^/\\]+[/\\].+\.css$/,
};
//Exclude CKEditor regex from mix's default rules
Mix.listen('configReady', config => {
const rules = config.module.rules;
const targetSVG = (/(\.(png|jpe?g|gif|webp|avif)$|^((?!font).)*\.svg$)/).toString();
const targetFont = (/(\.(woff2?|ttf|eot|otf)$|font.*\.svg$)/).toString();
const targetCSS = (/\.p?css$/).toString();
rules.forEach(rule => {
let test = rule.test.toString();
if ([targetSVG, targetFont].includes(rule.test.toString())) {
rule.exclude = CKEditorRegex.svg;
} else if (test === targetCSS) {
rule.exclude = CKEditorRegex.css;
}
});
});
mix.webpackConfig({
plugins: [
new CKEditorWebpackPlugin({
language: 'en',
addMainLanguageTranslationsToAllAssets: true
}),
],
module: {
rules: [
{
test: CKEditorRegex.svg,
use: ['raw-loader']
},
{
test: CKEditorRegex.css,
use: [
{
loader: 'style-loader',
options: {
injectType: 'singletonStyleTag',
attributes: {
'data-cke': true
}
}
},
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: CKEditorStyles.getPostCssConfig({
themeImporter: {
themePath: require.resolve('#ckeditor/ckeditor5-theme-lark')
},
minify: true
})
}
}
]
}
]
}
});
Specs:
node v.16.11.1
npm v.8.0.0
Laravel v.8.77.1
package.json
"laravel-mix": "6.0.40",
"postcss-loader": "^6.2.1",
"raw-loader": "^4.0.1",
"sass": "^1.49.4",
"sass-loader": "^12.4.0",
"style-loader": "^2.0.0"
The Mix.listen() was deprecated and will go away in a future release. should replaced by mix.override().
Thanks #bakis.
This is the only working version after hours of searching. Exclude CKEditor regex from mix's default rules is the key neglected.
/** ckeditor 5 webpack config ****/
const CKEditorWebpackPlugin = require('#ckeditor/ckeditor5-dev-webpack-plugin');
const CKEditorStyles = require('#ckeditor/ckeditor5-dev-utils').styles;
//Includes SVGs and CSS files from "node_modules/ckeditor5-*" and any other custom directories
const CKEditorRegex = {
svg: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/, //If you have any custom plugins in your project with SVG icons, include their path in this regex as well.
css: /ckeditor5-[^/\\]+[/\\].+\.css$/,
};
mix.webpackConfig({
plugins: [
new CKEditorWebpackPlugin({
language: 'en',
addMainLanguageTranslationsToAllAssets: true
}),
],
module: {
rules: [
{
test: CKEditorRegex.svg,
use: ['raw-loader']
},
{
test: CKEditorRegex.css,
use: [
{
loader: 'style-loader',
options: {
injectType: 'singletonStyleTag',
attributes: {
'data-cke': true
}
}
},
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: CKEditorStyles.getPostCssConfig({
themeImporter: {
themePath: require.resolve('#ckeditor/ckeditor5-theme-lark')
},
minify: true
})
}
}
]
}
]
}
});
//Exclude CKEditor regex from mix's default rules
mix.override(config => {
const rules = config.module.rules;
const targetSVG = (/(\.(png|jpe?g|gif|webp|avif)$|^((?!font).)*\.svg$)/).toString();
const targetFont = (/(\.(woff2?|ttf|eot|otf)$|font.*\.svg$)/).toString();
const targetCSS = (/\.p?css$/).toString();
rules.forEach(rule => {
let test = rule.test.toString();
if ([targetSVG, targetFont].includes(rule.test.toString())) {
rule.exclude = CKEditorRegex.svg;
} else if (test === targetCSS) {
rule.exclude = CKEditorRegex.css;
}
});
});

Gulp 4 error: The following tasks did not complete: Did you forget to signal async completion?

I get this error when isDev = false. Here is my part of gulpfile.js
function CSSLoaders(isDev) {
let loaders = []
isDev ? loaders.push('vue-style-loader') : loaders.push(MiniCssExtractPlugin.loader)
loaders.push({
loader: 'css-loader',
options: {
url: false,
sourceMap: isDev,
importLoaders: isDev ? 1 : 2,
modules: {
localIdentName: "[local]"
}
}
})
if (!isDev) {
loaders.push('postcss-loader')
loaders.push({
loader: 'string-replace-loader',
options: {
multiple: [...Array(100).fill({search: '../..', replace: ''})]
}
})
}
return loaders
}
function webpackConfig(isDev) {
return {
output: {
filename: '[name].js'
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
// 'vue': 'vue/dist/vue.esm-bundler.js',
'vue': 'vue/dist/vue.esm.js',
// 'mixins-c': path.resolve(__dirname, '../../sass/_mixins-c.scss;')
}
},
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: CSSLoaders(isDev)
},
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: '/node_modules/'
}
]
},
plugins: [
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: isDev ? 'css/[name].css' : 'skin/lightui/css/[name].css'
}),
// new cssoLoader(),
new webpack.LoaderOptionsPlugin({
minimize: true
})
],
optimization: {
minimizer: [
new UglifyJsPlugin({
sourceMap: false,
uglifyOptions: {
warnings: false,
compress: true
}
})
],
},
mode: isDev ? 'development' : 'production',
devtool: isDev ? 'eval-source-map' : 'none'
}
};
function js_build() {
return src(['src/pages/**/js/*.js'])
.pipe(named())
.pipe(webpackStream(webpackConfig(false)))
.pipe(dest('dist/js/'))
}
let build = gulp.series(js_build)
exports.build = build
I tried
async function js_build() {
return await src(['src/pages/**/js/*.js'])
.pipe(named())
.pipe(webpackStream(webpackConfig(false)))
.pipe(dest('dist/js/'))
}
and
var print = require('gulp-print');
function js_build() {
return src(['src/pages/**/js/*.js'])
.pipe(named())
.pipe(webpackStream(webpackConfig(false)))
.pipe(dest('dist/js/'))
.pipe(print.default(function() { return 'HTTP Server Started'; }));
}
But got the same error. I've found out that the problem disappear with block in function CSSLoaders():
if (!isDev) {
loaders.push('postcss-loader')
loaders.push({
loader: 'string-replace-loader',
options: {
multiple: [...Array(100).fill({search: '../..', replace: ''})]
}
})
}
I dont understand why i can use "css-loader" without mistakes and cannot "postcss-loader", what the difference? Where should i put the sign, that async is completed?
Can anyone help me understand what i should do?
Using callback and onEnd method should do the trick.
function js_build(callback) {
return src(['src/pages/**/js/*.js'])
.pipe(named())
.pipe(webpackStream(webpackConfig(false)))
.pipe(dest('dist/js/'))
.pipe(print.default(function() { return 'HTTP Server Started'; }))
.on('end', function () {
callback();
});
}
This question was answer here :
Gulp error: The following tasks did not complete: Did you forget to signal async completion?

How Grunt watches children folder src, and putting output in same child dest?

I am new to NodeJs and Grunt, and I want to ask a question that is probably already answered, but I either couldn't understand solution, or couldn't find it.
So, I have www folder with many subfolders with projects. Every project has same folders inside,
--css/style.css
--sass/style.scss
--js/script.js + /1.js + /2.js
--build/script.js
--build/style.css
My Gruntfile.js with grunt is at www folder, and my grunt concat, goes something like this:
grunt.initConfig({
concat: {
dist: {
src: ['**/js/1.js', '**/js/2.js', '**/js/script.js'],
dest: '**/build/script.js'
},
},
});
Now, you can probably see the problem, I get error "Can't create directory C/wamp/www/** ..., and I need to be able to select same folder as where it found js (and later css and other tasks as well).
The most simple solution is needed, and I plan to use concat, watch, uglify, sass (solution for sass is welcome as well).
I am apologizing if this question is repeated, but I can't find an answer.
You cannot use a globbing pattern for your dest value, as globbing is for matching patterns. You will need a separate src -> dest mapping for each project subfolder. There are a few ways to do this, but I will use the Files Object Format. Assuming project subfolders named proj1/ and proj2/, the configuration would look like the following:
concat: {
dist: {
files: {
'proj1/build/script.js': 'proj1/js/*.js',
'proj2/build/script.js': 'proj2/js/*.js'
}
}
}
If you are going to keep adding project subfolders, it might make sense to build the concat configuration dynamically:
var project_dirs = ['proj1', 'proj2'];
var concat_config = {
dist: {}
};
concat_config.dist.files = project_dirs.reduce(function (memo, dir) {
var src = dir + '/js/*.js';
var dest = dir + '/build/script.js';
memo[dest] = src;
return memo;
}, {});
grunt.initConfig({
concat: concat_config
});
First
Concat and uglify your js:
concat.dev = {
files: {
"public/myapp.development.js": [
"with-bootstrap/public/js/vendor", "with-bootstrap/public/js/**/*.js"
]
}
};
//Uglify ===============================
config.uglify = {
dist: {
options: {
sourceMap: "public/myapp.production.js.map"
},
files: {
"public/myapp.production.js": ["public/myapp.development.js"]
}
}
}
and your sass:
//Sass ===============================
var sass;
config.sass = sass = {};
//distribution
sass.dist = {
options: {
style: "compressed",
noCache: true,
sourcemap: 'none',
update: true
},
files: {
"<%= src.distFolder %>": "<%= src.sassMain %>"
}
};
//development env.
sass.dev = {
options: {
style: "expanded",
lineNumber: true,
},
files: {
"<%= src.devFolder %>": "<%= src.sassMain %>"
}
};
watch your changes in that case I am watching just sass directory:
//Watch ===============================
config.watch = {
scripts: {
files: ["<%= src.libFolder %>", "<%= src.sassFolder %>"],
tasks: ["dev", "sass:dist"]
//,tasks: ["dev",'sass:dist']
}
}
anyway I hope that helps you for start.

file to import not found or unreadable: "compass"

I am receiving the error "file to import not found or unreadable: "compass"" when I am attempting to run my "grunt" task.
"Running "sass:app" (sass) task"
Warning: build/global/css/base:1: file to import not found or unreadable: "compass"
Here is my gruntfile:
module.exports = function(grunt) {
// COMMANDS
// comple css and js - $ grunt
// optim - run $ grunt imgoptim
// FILE STRUCTURE
// css/app.css, css/app.min.css
// build/global/css/*.scss
// build/global/css/**/*.scss
// build/components/componentname/css/*.scss
// css/singlefile.css, css/singlefile.min.css
// build/global/solo/css/*.scss
// js/app.js, js/app.min.css
// build/global/js/*.js
// build/global/js/**/*.js
// build/components/componentname/js/*.js
// singlefile.js, singlefile.min.js
// build/global/solo/js/*.js
var watch = {};
var uglify = {};
var concat = {};
var sass = {};
var cssmin = {};
var js_files = [
'build/global/js/vendor/respond.js',
'build/global/js/vendor/AccessifyHTML5.js',
'build/global/js/vendor/jquery.equalHeights.js',
'build/global/js/vendor/jquery.infinitescroll.js',
'build/global/js/vendor/jquery.verticalcentering.js',
'build/global/js/global.js',
'build/components/**/js/vendor/*.js',
'build/components/**/js/*.js'
];
// WATCH =========================================/
watch.solocss = {
options: { livereload: true }, // currently not working correctly, should be able to remove this line
livereload: {
options: { livereload: true },
files: ['css/*.css', '!css/*.min.css']
},
files: 'build/solo/css/*.scss',
tasks: [
'newer:sass:solo'
]
};
watch.appcss = {
options: { livereload: true }, // currently not working correctly, should be able to remove this line
livereload: {
options: { livereload: true },
files: ['css/*.css', '!css/*.min.css']
},
files: [
'build/global/css/**/*.scss',
'build/global/css/*.scss',
'build/components/**/*.scss'
],
tasks: [
'sass:app',
'concat:appcss',
'sass:solo' // run solo here too incase there are changes to sass vars etc
]
};
watch.cssmin = {
files: ['css/*.css', '!css/*.min.css'],
tasks: [
'newer:cssmin:compress',
]
};
watch.solojs = {
options: { livereload: true }, // currently not working correctly, should be able to remove this line
livereload: {
options: { livereload: true },
files: ['js/*.js', '!js/*.min.js']
},
files: 'build/solo/js/*.js',
tasks: [
'newer:uglify:solojsdev',
'newer:uglify:solojsprod'
]
};
watch.globaljs = {
options: { livereload: true }, // currently not working correctly, should be able to remove this line
livereload: {
options: { livereload: true },
files: ['js/*.js', '!js/*.min.js']
},
files: ['build/global/js/*.js', 'build/global/js/**/*.js', 'build/components/**/*.js'],
tasks: [
'concat:appjs',
'uglify:appjs'
]
};
// CSS COMPLILATION ====================================/
//solo files, compiled to /css/file.css
sass.solo = {
options:{
includePaths: require('node-bourbon').with('build'),
sourceComments: true,
style: 'expanded', // compile in expanded format with comments for dev,
compass: true
},
files: [{
expand: true,
src: watch.solocss.files, // where it's coming from
dest: 'css', // where it's going
flatten: true, // removes folder tree
ext: '.css', // what file extension to give it - standard
extDot: 'last'
}]
};
// app scss files, compiled individually to /css/build/...
sass.app = {
options:{
includePaths: require('node-bourbon').with('build'),
style: 'expanded', // compile in expanded format with comments for dev
sourceComments: 'normal',
},
files: [{
//cwd: 'build',
expand: true,
src: watch.appcss.files, // where it's coming from
dest: 'css', // where it's going
ext: '.css' // what file extension to give it - standard
}]
};
// concat app.css files
concat.appcss = {
src: [
'css/build/global/css/**/*.css',
'css/build/global/css/*.css',
'css/build/components/**/*.css'
],
dest: 'css/app.css',
seperator: '\n'
};
// create compressed version of all css files for prod
cssmin.compress = {
files: [{
expand: true,
cwd: 'css/',
src: ['*.css', '!*.min.css', '!editor.css'],
dest: 'css/',
ext: '.min.css',
extDot: 'last'
}]
}
// JAVASCRIPT COMPLILATION ============================/
// concat app.js files
concat.appjs = {
src: js_files,
dest: 'js/app.js',
separator: ';'
};
// minify app.js
uglify.appjs = {
files: {
'js/app.min.js': [
'js/app.js'
]
}
};
// uglify solo files for dev
uglify.solojsdev = {
options: {
compress: false,
mangle: false,
beautify: true
},
files: [{
expand: true,
flatten: true, // removes folder tree
src: watch.solojs.files,
dest: 'js/'
}]
};
// uglify + minify solo files for prod
uglify.solojsprod = {
options: {
compress: true
},
files: [{
expand: true,
flatten: true, // removes folder tree
src: watch.solojs.files,
dest: 'js/',
ext: '.min.js',
extDot: 'last',
}]
};
// IMAGE OPTIMISATION ==========================/
imageoptim = {
optimise: {
src: ['images']
}
}
// GRUNT ======================================/
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: watch,
sass: sass,
concat: concat,
cssmin: cssmin,
uglify: uglify,
imageoptim: imageoptim
});
// DEPENDENT PLUGINS =========================/
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-imageoptim');
grunt.loadNpmTasks('grunt-newer');
// TASKS =====================================/
grunt.registerTask('default', [
'sass',
'concat',
'newer:cssmin',
'newer:uglify',
'watch'
]);
grunt.registerTask('imgoptim', [
'imageoptim'
]);
}
My directory structure looks like the following relative from the gruntfile.js:
/build/global/components/FOLDERS/*.scss files
/build/global/css/FOLDERS & *.scss files
/dist/*.css files
Here is my config.rb file in the same directory as the gruntfile:
http_path = "/"
css_dir = "css"
sass_dir = "build"
images_dir = "images"
javascripts_dir = "javascript"
I already have compass installed and all the node_modules.

Grunt "watch.sass.files" missing

Beginning with Grunt, which I love but cannot make it work as I get continously an error with my sass implementation. I get the following alerts:
Danis-MacBook-Pro:020 DanielRamirez$ grunt
Running "concat:dist" (concat) task
File "js/build/production.js" created.
Running "uglify:build" (uglify) task
File js/build/production.min.js created.
>> No "sass" targets found.
Warning: Task "sass" failed. Use --force to continue.
Aborted due to warnings.
Danis-MacBook-Pro:020 DanielRamirez$
If I --force I get the following:
Danis-MacBook-Pro:020 DanielRamirez$ grunt
Running "concat:dist" (concat) task
File "js/build/production.js" created.
Running "uglify:build" (uglify) task
File js/build/production.min.js created.
>> No "sass" targets found.
Warning: Task "sass" failed. Use --force to continue.
Aborted due to warnings.
Danis-MacBook-Pro:020 DanielRamirez$
This is my Gruntfile.js:
module.exports = function(grunt) {
// 1. All configuration goes here
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// 2. Configuration for concatinating files goes here.
// Concatonate various files into one
concat: {
dist: {
src: [
'js/vendor/*.js', // All JS in the libs folder
'js/plugin.js', // All JS in the libs folder
'js/global.js' // This specific file
],
dest: 'js/build/production.js',
}
},
// Creates a minified version of the javascript files of the project
uglify: {
build: {
src: ['js/vendor/*.js', 'js/plugin.js', 'js/global.js'],
dest: 'js/build/production.min.js'
}
},
// Minifies automatically the images of the project
// imagemin: {
// dynamic: {
// files: [{
// expand: true,
// cwd: 'images/',
// src: ['**/*.{png,jpg,gif}'],
// dest: 'images/build/'
// }]
// }
// },
// Watches for changes done on the project and builds the commands if neccesary
watch: {
options: {
livereload: true,
},
scripts: {
files: ['js/*.js'],
tasks: ['concat', 'uglify'],
options: {
spawn: false,
},
},
sass: {
dist: {
options: {
style: 'compressed'
},
files: {
'css/build/style.css': 'sass/style.scss'
}
}
},
css: {
files: ['css/*.scss'],
tasks: ['sass'],
options: {
spawn: false,
}
}
}
});
// 3. Where we tell Grunt we plan to use this plug-in.
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
// grunt.loadNpmTasks('grunt-contrib-imagemin');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-compass');
grunt.loadNpmTasks('grunt-contrib-watch');
// 4. Where we tell Grunt what to do when we type "grunt" into the terminal.
grunt.registerTask('default', ['concat', 'uglify', 'sass', 'compass', 'watch']);
};
Any ideas?
Yes, what you've done is put the entire Sass configuration inside the watch config. Grunt does not work this way. Instead, change your config to something like this:
module.exports = function(grunt) {
// 1. All configuration goes here
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// 2. Configuration for concatinating files goes here.
// Concatonate various files into one
concat: {
dist: {
src: [
'js/vendor/*.js', // All JS in the libs folder
'js/plugin.js', // All JS in the libs folder
'js/global.js' // This specific file
],
dest: 'js/build/production.js',
}
},
// Creates a minified version of the javascript files of the project
uglify: {
build: {
src: ['js/vendor/*.js', 'js/plugin.js', 'js/global.js'],
dest: 'js/build/production.min.js'
}
},
// Compile sass to css
sass: {
dist: {
options: {
style: 'compressed'
},
files: {
'css/build/style.css': 'sass/style.scss'
}
}
},
// Minifies automatically the images of the project
// imagemin: {
// dynamic: {
// files: [{
// expand: true,
// cwd: 'images/',
// src: ['**/*.{png,jpg,gif}'],
// dest: 'images/build/'
// }]
// }
// },
// Watches for changes done on the project and builds the commands if neccesary
watch: {
options: {
livereload: true,
},
scripts: {
files: ['js/*.js'],
tasks: ['concat', 'uglify'],
options: {
spawn: false,
},
},
css: {
files: ['css/*.scss'],
tasks: ['sass'],
options: {
spawn: false,
}
}
}
});
// 3. Where we tell Grunt we plan to use this plug-in.
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
// grunt.loadNpmTasks('grunt-contrib-imagemin');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-compass');
grunt.loadNpmTasks('grunt-contrib-watch');
// 4. Where we tell Grunt what to do when we type "grunt" into the terminal.
grunt.registerTask('default', ['concat', 'uglify', 'sass', 'compass', 'watch']);
};

Resources