PurgeCSS: How to define path to all subdirectories? - glob

The basic postcss.config.js looks like this
const purgecss = require('#fullhuman/postcss-purgecss')
module.exports = {
plugins: [
purgecss({
content: ['./**/*.html']
})
]
}
I have a situation where I need to define the path to a folder with nested subdirectories. The only explanation I found was this one:
content: [
// keep only those that you need
'**/*.html' // will look inside any folder for an .html file
'!(bar)/**/*.html' // will look inside any folder that is not 'bar'
'!({bar,foo})/**/*.html' // will look inside any folder that is nor 'bar' nor 'foo'
'!(bar-*)/**/*.html' // will look inside any folder that does not start with 'bar-'
],
css: [`**/*.css`],
...but I want something different: How to define the path to a folder and all his subdirectories (and their subdirectories and so on)?
There is something like
glob.glob('**/*.txt',recursive=True): matches all files ending in '.txt' in the current directory and in all subdirectories
How to set the option recursive=True in PostCSS/PurgeCSS?

My postcss.config.js looks like this:
const themeDir = __dirname + '/../../';
const purgecss = require('#fullhuman/postcss-purgecss')({
// Specify the paths to all of the template files in your project
content: [
themeDir + 'layouts/**/*.html',
themeDir + 'content/**/*.html',
'layouts/**/*.html',
'content/**/*.html',
// Specify path to own javascript
themeDir + 'assets/js/**/*.js',
],

Related

Combining Relative Files in Gulp

I need to combine some HTML files with the CSS that resides in the same directory using Gulp. The file structure of my project is as follows.
- src
- dir1
- index.html
- style.css
- dir2
- index.html
- style.css
- dir3
- index.html
- style.css
So, I'm combining the HTML and CSS from dir1, then the HTML and CSS from dir2, and so on.
I've tried to do this several ways (including the following) but can't get anything to work the way I want.
.pipe(replace('<link rel="stylesheet" href="style.css">', function (match, p1) {
return '<style>' + fs.readFileSync('src/' + p1, 'utf8') + '</style>';
}))
Is there an easy way to reference relative files in Gulp?
I assume you are using gulp 4 and gulp-replace, and that your gulpfile.js is located in the project directory, next to the src subdirectory.
Then the task consists of three steps:
read the index.html files
replace the string <link rel="stylesheet" href="style.css"> with a <style> tag with the contents of the file style.css in the same directory as index.html.
write the changed index.html files to a new destination directory.
Steps 1 and 3 are easy to accomplish with gulp.src and gulp.dist, so let's look at step 2. Each style.css (the file we want to read) resides in the same directory as index.html. That directory can be retrieved with this.file.dirname in the gulp-replace callback. If we append "style.css" to that directory, we will get a full path to a CSS file that can be read with readFileSync. The rest is pretty straightforward:
const { readFileSync } = require('fs');
const gulp = require('gulp');
const replace = require('gulp-replace');
const { join } = require('path');
exports.default = () =>
gulp.src('src/**/index.html')
.pipe(replace('<link rel="stylesheet" href="style.css">', function () {
const stylePath = join(this.file.dirname, 'style.css');
const style = readFileSync(stylePath);
return `<style>${style}</style>`;
}))
.pipe(gulp.dest('dest'));
I really think that the only unobvious part in this process is getting the directory of each index.html/style.css file pair in the gulp-replace callback as this.file.dirname. Here, according to gulp-replace:
The value of this.file will be equal to the vinyl instance for the file being processed.
and file.dirname for a vinyl file
Gets and sets the dirname of file.path. Will always be normalized and have trailing separators removed.

How to find all files in one directory that match files in other directory in gulp using del?

Basically, as part of my clean task, I'd like to delete in the root folder all files that are present in my src folder, automatically. Because there are files in the root that aren't in src, I can't just delete all of them, and I'd like to keep the process dynamic (automatically determine matching files) rather than manual (explicitly listing the files to delete).
Right now, I'm doing this manually:
const deleteViewFiles = done => {
del.sync([
'./page-*.php',
'./header.php',
]);
done();
}
But what I'd like is, look at ./src/views/, find all direct descendants of ./src/views/ (not subfolders), and delete them at the root.
eg. Let's say in ./src/views/ I have page-1.php, header.php, my-dog.php, mermaid.html, I want to delete all those files from root without listing them in my delete task.
OK. Here's what I ended up doing.
I used glob to store all files in my src directory into an array.
Then, I replaced the view folder base path with root base path. Then I used this array as an argument for my del function.
(I stored paths in a config file, here's a snippet (the real object is much bigger):)
paths = {
views: {
src: `${dirs.src}views/`,
dest: `${dirs.base}views/`,
rootFiles: `${dirs.src}views/*.*`,
folders: `${dirs.src}views/*/*`
}
}
import { paths } from '../config';
const clean = done => {
// get all files at root of views directory
const viewsDirRootFiles = glob.sync(paths.views.rootFiles);
// replace views dir in base of filepaths with root
const rootFiles = viewsDirRootFiles.map(f => f.replace(paths.views.src, paths.dirs.base));
// combine root view files with other folders/files to delete to generate final deletion-target array
const filesToDelete = [
...rootFiles,
'./views',
];
del.sync(filesToDelete);
done();
}

Gulp partially remove directories structure

My directories structure is similar to this:
app/
directory1/
assets/
images/
js/
directory2/
assets/
images/
dist/
assets/
images/
js/
What I try to achieve using Gulp is to "gather" assets from directories 1, 2, ... and place them into the dist/assets/ so I wrote this:
gulp.task('gather-assets', function() {
gulp.src('app/*/assets/**').pipe(gulp.dest('dist/assets/'));
});
The problem is that after running this function it will create a path like this:
dist/assets/directory1/assets/images
Following the recommendations from this question I tried to use gulp-rename, but my case is different, and if I use gulp-rename like this:
gulp.task('gather-assets', function() {
gulp.src('app/*/assets/**').pipe(rename({dirname: ''})).pipe(gulp.dest('dist/assets/'));
});
it will surely remove unnecessary path at the place of * asterisk, but it will remove the ** path as well. So files from both images/ and js/ will be copied to assets/ without subdirectories. What solution is available for me for this scenario?
Gulp-flatten will work for you.
var flatten = require('gulp-flatten');
gulp.task('gather-assets', function() {
return gulp.src('app/*/assets/**')
// .pipe(rename({ dirname: '' }))
// -2 will keep the last two parents : assets/images or assets/js
.pipe(flatten({ includeParents: -2 }))
.pipe(gulp.dest('dist'));
});
And if you wanted to use gulp-rename: [both gulp-flatten and gulp-rename are just doing string manipulations of each file's directory structure]
// .pipe(flatten({ includeParents: -2 }))
.pipe(rename(function (file) {
let tempArray = file.dirname.split(path.sep);
// remove the first array item : directory1 or directory2
// rejoin the remaining array items into a directory string
let temp = tempArray.slice(1).join(path.sep);
file.dirname = temp;
}))

Bower. How to set base forder for main directories?

I override the main directories for the Bootstrap in bower.json:
"main" : [
"./dist/css/bootstrap.css",
"./dist/css/bootstrap.css.map",
"./dist/css/bootstrap-theme.css",
"./dist/css/bootstrap-theme.css.map",
"./dist/js/bootstrap.js",
"./dist/fonts/*",
"./less/**"
]
And I want that a files were copied with css, js, fonts folders. I.e. can I set '/dist/' as a base forder?
Or can I do it in the gulp task? In gulpfile.js I wrote:
var files = mainBowerFiles('**/dist/**');
return gulp.src( files, {base: 'C:/Users/Den/Desktop/HTML5-Demo/bower_components/bootstrap/dist/'} )
.pipe( gulp.dest('public_html/libs') );
But I'm forced to write a full path which of course is bad. Is there way to use a relative path?
Also I want to ask what does '.' in the beginning of the directories mean?
To use relative path you need to get current working directory.
var path = require('path');
var cwd = process.cwd(); // current working directory
var basePath = path.resolve(cwd, "bower_components/bootstrap/dist");
The next code works:
var stream = gulp.src(files, {base: './bower_components/bootstrap/dist'})

gulp-inject is giving wrong relative path

I've been having trouble with this useful tool and I don't know what to do anymore, that's why I come here to ask for your help.
This is my directory structure:
- Project root
|- dist
|-css
|-js
|- source
|- css
|- js
|-index.html
|-gulpfile.js
|-index.html
So, I'm using gulp to inject my css,js from the source folder, into my dist folder, minified, concatenated, etc. Then, inject that into my index.html in the source folder and spit in on the project root folder.
This is the code:
//Injects assets (css,js) into index.html automatically
gulp.task('inject',['sass','concat-css','concat-js'],function(){
//Target to inject
var target = gulp.src('source/index.html');
//Sources to be injected
var cssFiles = gulp.src('./dist/assets/css/*.css',{read:false});
var jsFiles = gulp.src('./dist/assets/js/*.js',{read:false});
//Merge resources into one
var sources = es.merge(cssFiles,jsFiles);
//Injecting bower.json dependencies and other resources
return target.pipe(inject(sources),{
ignorePath:'dist/',
addRootSlash:false
})
.pipe(wiredep({ignorePath:'../'}))
.pipe(gulp.dest('./'));
});
The issue is that the path to the dist folder on the index.html is like this:
"/dist/css/stylesheet.css"
Causing error, because it should be : `"dist/css/stylesheet.css"
As you can see in the code, I've used the inject's options, ignorePath, addRootSlash, relative:true , and nothing seems to work. The same thing was happening to wiredep, but this one is accepting the ignorePath options so everything is fine.
Thanks in advance for your help.
It looks like you mistakenly put the inject options as a second parameter on the pipe function. Try:
target.pipe(inject(sources, { ignorePath: 'dist/', addRootSlash: false }))
You should set relative option in the inject like this:
inject(sources, { relative: true })
you can use the two option od gulp inject:
ignorePath and addRootSlash
var injectOptions = {
addRootSlash: false,
ignorePath: 'dist/'
};
target.pipe(inject(sources),injectOptions)
I know, this is old.
But for everyone with the same problem, like in my case.
Setting
var options = {
relative: false,
addRootSlash: false,
ignorePath: 'dist/',
addPrefix: './js'
};
return gulp.src(['./index.html'])
.pipe(inject(stream, options))
.pipe(gulp.dest('temp/'));
does the trick for me.
I had to remove the path by setting 'ignorePath' and then 'removeRootSlash' and 'addPrefix' for the destination folder.
See the More Examples section at npm gulp-inject and the addPrefix part.