Using Gulp to build csproj on .less change - javascript

I am currently trying to come up with a gulp task that will build the entire .csproj file associated with a particular .less file whenever that .less file changes.
I already have a working task that will do just that, however the restriction I am facing is that the .less file must be in a specific place relative to the .csproj file. If the .less file is one level deeper/higher in the directory, the method I am using to build the .csproj file wont be able to find the correct .csproj file to build.
My current task is based heavily off of one of the tasks found in Kamsar's Habitat repo for Sitecore: https://github.com/kamsar/Habitat
It is as follows:
gulp.task("Auto-Publish-Less",
function() {
var root = "./src";
var roots = [root + "/**/resources/styles", "!" + root + "/**/obj/**/resources/styles"];
var files = "/**/*.less";
gulp.src(roots, { base: root })
.pipe(
foreach(function (stream, rootFolder) {
console.log(rootFolder);
gulp.watch(rootFolder.path + files,
function(event) {
if (event.type === "changed") {
var dest = config.websiteRoot;
console.log("Build project associated with this file: " + event.path);
return gulp.src([event.path + "/../../../*.csproj"]).pipe(publishStream(stream,dest));
}
});
return stream;
}));
});
This works great so long as the .csproj file is 3 levels higher than the .less file. I could also add more wildcards for 2 levels higher, 1 level higher, etc. However, I was looking to see if there was a way in gulp.src to "find" the first matching file, moving up the directory structure, and then stopping once the first match is found. Is there a way to do this in gulp and/or plain-old js?

Check out this package:
Finds the first parent directory that contains a given file or directory:
https://www.npmjs.com/package/find-parent-dir

Related

how to remove templateCache with gulp?

i use angular-template-cache.
follow code exist for remove template cache in app module but i need to remove all templateCache with gulp on dev machine.
myApp.run(function($rootScope, $templateCache) {
$rootScope.$on('$viewContentLoaded', function() {
$templateCache.removeAll();
});
});
The best way to avoid template caching is revisioning your files.
Since you are using gulp, you can revision your files using gulp-rev or gulp-rev-all.
What is revisioning?
Static asset revisioning by appending content hash to filenames unicorn.css → unicorn-d41d8cd98f.css.
i.e., On every builds the filename changes and that way avoiding template caching.
You can revision every file including .html, .css, .js, images, videos etc.
Since gulp-rev-all is the latest and forked from gulp-rev, let's talk about gulp-rev-all only.
Revisioning using gulp-rev-all:
var revAll = require('gulp-rev-all');
if you want to neglect some files from revisioning, you can do that like this.
var rev = new revAll({dontRenameFile: [/^\/favicon.ico$/g, /^\/index.html/g]})
Consider all your files are in the folder dist and save the new revisioned files in the folder www.(You can save them in dist also. Considering www is your build directory.)
return gulp.src('dist/**')
.pipe(rev.revision())
.pipe(gulp.dest('www'))
Next, create a manifest file to map your files with the revisioned one. for that use .manifestFile() function. which returns a transform function that will filter out any existing files going through the pipe and will emit a new manifest file. Must be called after .revision().
.pipe(rev.manifest())
.pipe(gulp.dest('www/manifest'));
An asset manifest, mapping the original paths to the revisioned paths, will be written to www/manifest/rev-manifest.json:
{
"css/unicorn.css": "css/unicorn.098f6bcd.css",
"js/unicorn.js": "js/unicorn.273c2cin.js"
.....
.....
}
Complete code:
gulp.task('rev', () => {
var revAll = require('gulp-rev-all'),
rev = new revAll({dontRenameFile: [/^\/favicon.ico$/g, /^\/index.html/g]});
return gulp.src('dist/**')
.pipe(rev.revision())
.pipe(gulp.dest('www'))
.pipe(rev.manifest())
.pipe(gulp.dest('www/manifest'));
});
Read more about gulp-rev-all here

How to rename the original files of scripts in index.html using gulp?

I've written a gulp task to rename files so that they can be versioned. The problem is that the filenames of the files that the index.html scripts reference are not changed.
For example, in my index.html:
<script src=pub/main_v1.js"></script>
But if you actually navigate through the build folder to the subdirectory pub, you will find main.js.
Here is the custom gulp task:
const gulpConcat = require('gulp-concat');
const gulpReplace = require('gulp-replace');
const version = require('./package.json').version;
gulp.task('version', function () {
var vsn = '_' + version + '.js';
gulp.src('scripts/**/*.js')
.pipe(gulpConcat(vsn))
.pipe(gulp.dest('./prodBuild'));
return gulp.src('./prodBuild/index.html', { base: './prodBuild' })
.pipe(gulpReplace(/* some regex */, /* append vsn */))
.pipe(gulp.dest('./prodBuild'));
});
What do I need to fix/add so that the original filename changes to match that in the script tag?
Note: According to the gulp-concat docs, I should be able to find the concated files at prodBuild/[vsn], where [vsn] is _v1.js. However, it is no where to be found.
Update: The files rename properly in index.html, but I can't seem to get the renaming of the original files to work. Here's a snapshot of my build directory:
prodBuild/
pub/
main.js
someDir/
subDirA/
// unimportant stuff
subDirB/
file2.js
file3.js
// ...other files and folders...
EDIT:
The issue is that you return only one of the two tasks. The first task is simply ignored by gulp, since it is not returned. A simple solutions: Split it into two tasks, and reference the one from the other, like in this SO answer.
Old Answer
This looks like a perfect case for the gulp-rename. You could simply pipe your scripts through gulp-rename, like this:
.pipe(rename(function (path) {
path.basename += vsn;
path.extname = ".js"
}))
Gulp concat is, AFAIK, made for the concatination of files, not particularly for the renaming of them.

Using Gulp and Gulp Replace Name to clone a project but rename files that contain a certain word inside multiple folders

I need to use gulp to create a clone of a project and change all file types that start with a specific word to have a different word. I have tried using gulp-replace-name.
Below is a simplified example of the folder structure of the project I want to clone. In the real project there are multiple nested folders.
originalProject/
- readme.txt
- index.php
- originalProject.info.php
- originalProject.setup.php
- assets/
- originalProject.css
- originalProject.js
- staticAssets.css
And here is an example of the cloned project:
cloneProject/
- readme.txt
- index.php
- cloneProject.info.php
- cloneProject.setup.php
- assets/
- cloneProject.css
- cloneProject.js
- staticAssets.css
As you can see, files that start with "originalProject" need to have that text replaced with "cloneProject". You will also notice that there are folders as well as other files which do not need to have their filename changed. Finally, some of the file names contain more than one period in the filename.
Here is the code I created when using gulp-replace-name. This works if there are no folders in the project. When I add folders I get an error.
var gulp = require("gulp");
var changeFilename = require("gulp-replace-name");
gulp.task("duplicate", function () {
return gulp
.src("./orignalProject/**/*")
.pipe(changeFilename(/originalProject/g, "cloneProject"))
.pipe(gulp.dest("./cloneProject"));
});
gulp.task("default", ["duplicate"]);
This is my first post to stackoverflow. I am also new to gulp. Thank you in advance for any help you can provide.
It's a bug in gulp-replace-name. When it encounters a directory it tries to call a callback cb that doesn't exist, which leads to the error you receive. It also doesn't even attempt to rename directories, which you need.
I suggest you use the gulp-rename plugin instead. It's thoroughly tested and has had a large user base for years, so you're unlikely to run into problems like this.
This a bit more verbose, but does what you want:
var gulp = require('gulp');
var rename = require("gulp-rename");
gulp.task("duplicate", function () {
return gulp
.src("./originalProject/**/*")
.pipe(rename(function(file) {
file.dirname = file.dirname.replace(/originalProject/g, "cloneProject");
file.basename = file.basename.replace(/originalProject/g, "cloneProject");
}))
.pipe(gulp.dest("./cloneProject"));
});
gulp.task("default", ["duplicate"]);

Gulp copy list of folders with contents

I would like to copy a list of folders to a destination with gulp
So far i've come up with a working solution, but its far from performant.
The structure of my directory is like this:
App
src
web
some files...
and i would like to copy it to
build
src
web
the files
The code i am using to accomplish this is:
var paths = [path.app + '/src/', path.app + '/app/'].concat(path.assets);
paths.forEach(function(value, index){
// value.replace(path.app, path.build);
gulp.src(value + '/**/*')
.pipe(gulp.dest(value.replace(path.app, path.build)));
});
Where the assets are my files (or other directories)
However there is a loop and no clear return value. I am wondering if there is a more performant way of doing this
I'm not sure I understand what you're trying to do here (where is your gulp task definition for example?), but it seems like you just want to copy everything below App to the build folder while preserving directory structure.
If that's the case, you don't have to loop over the files and replace folder names yourself. Gulp does it for you:
gulp.task('default', function () {
return gulp.src('App/**')
.pipe( gulp.dest('build') );
});
Everything before the ** is automatically stripped from the path of files written to build, so you end up with build/src, build/web, etc ...

How to wait until a file is available in a Jake build (Node.js)?

Is there a way in a Node.js Jake build to wait until a certain file has been copied, and advance to do some operation only after the destination file can be found? I think this question pretty much comes down to "is there a way to copy files synchronously in Node.js/Jake?" (Perhaps something else than writing something from scratch, using the combination of fs.readSync and fs.writeSync.)
Background:
I'm developing a web app that is run on Node.js (with Express) during development, but will be deployed on a Java server in production. (We use Jade and Stylus in the client and Express enables us to run the app without generating all the HTML files etc. and deploying it after every change.)
I use Jake for making the build, i.e. generating HTML files from Jade files and CSS from Stylus files etc. Now I'm also trying to concatenate all of the app's JavaScript files into one minimized file and change all the HTML files to use that instead of all the separate JS files that are used in "raw" form during development.
However, I now have a problem with that last step. My idea was to copy all of my Jade files into a temporary directory for the deployment build and replace the reference (in a Jade file used as a header on all HTML pages) to a list of all separate JS files to the one that has just been generated by concatenating and minimizing the whole bunch. But as I first copy all of the Jade files to another location (which happens asynchronously) and try to edit one of the files, opening the file always fails since the copy operation hasn't really finished yet.
This is what I have now (in a simplified form) in my jakefile:
var fs = require('fs');
var fse = require('fs-extra');
var path = require('path');
var glob = require('glob');
var Snockets = require('snockets');
var snockets = new Snockets();
// generating the minimized JS file
snockets.getConcatenation(baseDir + '/scripts/all.js', { minify: true }, function(err, allJs) {
if (err) {
throw err;
}
fs.writeFileSync(generatedJsFileName, allJs);
});
// copying all the Jade files to a temp dir
glob.sync('**/*.*', {
cwd : srcDir
}).forEach(function(file) {
var loadPath = srcDir + '/' + file;
var savePath = targetDir + '/' + file;
fse.mkdirsSync(path.dirname(savePath));
fse.copy(loadPath, savePath);
});
// trying to read one of the copied files (which fails, since the file cannot be found yet)
fs.readFile(targetDir + '/views/includes/head.jade', 'utf8', function(err, data) {
...
});
This might be a stupid question, and a stupid way to try to solve the problem in the first place. So, also suggestions for a better approach are very welcome.
Update:
I also tried using Parseq, putting each operation (creating the JS file, copying the Jade files, reading one file) in its own function, but even that gives me the same error. If I run the script several times without deleting the target directory of the copy operation in between, the file can be found. So e.g. the path is correct and the problem really seems to be about timing.
I didn't really find an answer to the main question so I don't know if this helps anyone else facing the same problem. But I did find a way to get around the problem.
I ended using the same original Jade files for the two different conversions, but in the second conversion I use a custom js function to change the script tag reference to point to the minified file.
I.e.
var data = jade.compile(str, { filename: file, pretty: true })({
css: function(path) {
return '<link rel="stylesheet" href="/styles/' + path + '.css" />';
},
js: function(path) {
var name = '<script src="/scripts/';
if (path == 'all') {
name += generatedJsFileName;
}
else {
name += path + '.js';
}
name += '"></script>';
return name;
}
});
It might not be the prettiest workaround but it works.

Categories