Grunt-string-replace not working - gruntjs

I have an app folder where I want to replace http://localhost:8000 for http://fomoapp-melbourne.rhcloud.com in two files: companies-list.component.ts and events-list.component.ts. I am trying to use grunt-replace-string plugin and it seemingly runs successfully with green Done result and no errors, but no replacement happens.
Here is how Gruntfile.js looks like:
module.exports = function(grunt){
[
'grunt-string-replace',
].forEach(function(task){
grunt.loadNpmTasks(task);
});
// configure plugins
grunt.initConfig({
'string-replace': {
dist: {
files: {
'./app/': ['companies-list.component.ts','events-list.component.ts'],
},
options: {
replacements: [{
pattern: 'http://localhost:8000',
replacement: 'http://fomoapp-melbourne.rhcloud.com',
}]
}
}
},
});
// register tasks
grunt.registerTask('default', ['string-replace']);
};

The Grunt Files object is for specifying a mapping of source files to destination files. The purpose of this mapping is to tell Grunt to get the contents of the files in source, do something to the contents, and then write the response to a new file in the destination folder.
It looks to me from your configuration that you want Grunt to rewrite two files in the app/ directory. This is not going to work. I will bet that if you run grunt with the verbose option, grunt --verbose, your output will contain the following:
Files: [no src] -> ./app/
This is because Grunt cannot find the source files because you need to specify their relative paths.
It's up to you how you want to structure your app, but you might want to have a src/ folder and a dist/ folder under app/. If you choose to build your files objects dynamically, your config might look something like this:
files: [{
expand: true,
cwd: './app/src/',
dest: './app/dest/',
src: ['companies-list.component.ts', 'events-list.component.ts']
}]
Additionally, the documentation for grunt-string-replace states:
If the pattern is a string, only the first occurrence will be replaced, as stated on String.prototype.replace.
This means that if you want multiple instances of your string to be replaced, you must provide a Regular Expression literal. For example:
replacements: [{
pattern: /http:\/\/localhost:8000/g,
replacement: 'http://fomoapp-melbourne.rhcloud.com'
}]

Related

How to target all files in root folder and subfolders except some in Grunt

I'm trying to archive all files (including subfolders and files in them) in the root folder with some exceptions.
Here's the list of the files:
var fileList = [
'**/*',
'!archive.zip',
'!.sass-cache/*',
'!assets/*',
'!node_modules/*',
'!.bowerrc',
'!.editorconfig',
'!.gitattributes',
'!.gitignore',
'!.jshintrc',
'!bower.json',
'!Gruntfile.js',
'!package.json',
'!README.md',
'!sublime.sublime-project',
'!sublime.sublime-workspace',
];
And here's the grunt-contrib-compress config:
compress: {
main: {
options: {
archive: 'archive.zip'
},
files: [
{ src: [fileList], dest: 'archive/' }, // includes files in path
]
}
}
But I can't make it work. Seems that the process is stuck in endless loop and it keeps archiving itself over and over. I tried adding the name of the archive to the exception list, however it didn't help.
How can I get all the files archived from the root folder and subfolders with certain exceptions?
Thanks a lot.

Grunt convert markdown to pdf recursively and dynamically

I am stuck writing a Gruntfile which aim is to convert a bunch of Markdown files to PDF dynamically. Giving the current folder hierarchy:
root/
|_subfolder1
| |_filename1.md
|_subfolder2
|_filename2.md
...
|_node_modules
|_subfolderN
|filenameN.md
I would like to run a Markdown to PDF task which would process the md file and ouput a PDF file with the matching filename in the same output directory.
I did create a custom task which is parsing current directory, ignoring the mode_modules folder and get the markdown file, but I don't know how to configure the md2pdf task with the good properties to reflect dynamic folder mapping.
Here's my current Gruntfile:
module.exports = function(grunt) {
// 1 - Configuration
grunt.initConfig({
md2pdf: {
}
});
// 2 - Plugins
grunt.loadNpmTasks('grunt-md2pdf');
// 3 - Task registering
grunt.registerTask('default', 'Get Subfolders', function() {
grunt.file.recurse('.', callback);
function callback(abspath, rootdir, subdir, filename) {
var filenameOutExt;
// if current occurence is a file subdir == undefined
// checking subdir to true means it's not undefined and
// the current path is a directory
if(subdir) {
// excluding node_modules folder
if (!subdir.match('node_modules')) {
// only process markdown files
if(filename.match('.md')) {
filenameOutExt = filename.split('.')[0];
// now for each markdown files, run md2pdf task
// and ouput filenameOutExt.pdf in same folder
// as the input files
}
}
}
}
});
};
I am using this plugin: https://www.npmjs.com/package/grunt-md2pdf
So my questions is how should I configure the md2pdf task to pass it the markdown files and generate matching filename pdf output in same directory.
Output should be:
root/
|_subfolder1
| |_filename1.md
|_filename1.pdf
|_subfolder2
|_filename2.md
|_filename2.pdf
...
|_node_modules
|_subfolderN
|filenameN.md
|_filenameN.pdf
Thanks a lot
According to this line, this task uses the grunt.files utilitary function. This makes things easier for us!
First, it's not usual in grunt to create a different task to find the files you need in any other task.
That is, each task should receive the files it needs to operate on. For example...
coffee:
main:
files: [
expand: true
cwd: 'assets/script'
src: ['**/*.coffee']
dest: "assets/script"
ext: '.js'
]
(Note that this config is in a Gruntfile.coffee file, hence the CoffeeScript syntax)
This type of file configuration using glob expansion is one of the most common. You can find details in the documentation.
It's pretty obvious:
In every directory (**), take everything (/*) from assets/script/ that ends with .coffee. Put it into assets/script. Rename extensions to .js.
So, your task can probably be configured like that:
md2pdf: {
main: {
files: [ {
expand: true,
src: ['**/*.md', '!node_modules/**/*'],
dest: "pdf/"
} ]
}
}
Ok figured it out !
module.exports = function(grunt) {
// 2 - Plugins
grunt.loadNpmTasks('grunt-md2pdf');
grunt.registerTask('default', 'Dynamically generate PDF from MD', function() {
grunt.file.expand("./**/*.md").forEach( function(file) {
if(!file.match('./node_modules')) {
var md2pdf = grunt.config.get('md2pdf') || {};
md2pdf[file] = {
src: file,
dest: file + '.pdf'
};
grunt.config.set('md2pdf', md2pdf);
}
});
grunt.task.run('md2pdf');
});
};

Using grunt to concat many files from many dirs into single renamed file in new directory

I have an Angular project with potentially many modules. Each module has it's own directory with subdirectories for controllers, directives, services, etc. Something like this:
src
|-- js
|-- modules
|-- moduleOne
| module.js
|-- controllers
| listController.js
| detailController.js
|-- directives
| listItem.js
| summaryWidget.js
|-- filters
|-- services
| moduleService.js
My build essentially bundles and compiles files from src/ and puts into dev/, then minifies the files in dev/ and moves into prod/. During dev, the server points to the dev/ folder and in production, the server points to the prod/ folder (also why the files are ending in .min.js even though they are only compiled/concated). This process is working well.
Currently, my concat task is grabbing all the files in moduleOne/ and creating a single moduleOne.js file in my dev directory. This is what I want to happen, but more dynamically:
concat: {
modules: {
files: {
"dev/js/modules/moduleOne.min.js": [
"src/js/modules/moduleOne/*.js",
"src/js/modules/moduleOne/**/*.js"
],
"dev/js/modules/moduleTwo.min.js": [
"src/js/modules/moduleTwo/*.js",
"src/js/modules/moduleTwo/**/*.js"
]
}
}
}
The problem is that I have to do this for every module, but don't think I would need to.
I tried doing the following because it's sort of what I want to do:
concat: {
modules: {
files: [{
expand: true,
cwd: "src/js/modules",
src: "**/*.js",
dest: "dev/js/modules",
ext: ".min.js"
}]
}
}
But the result was all my files and directory structure moved over from src/ to dev/. I basically used concat to do a copy, not helpful.
I'd like to do something like this:
concat: {
modules: {
files: [{
expand: true,
cwd: "src/js/modules",
src: "**/*.js",
dest: "dev/js/modules/<foldername>.min.js", <- how do I achieve this?
}]
}
}
I've been reading a lot, but it seems that I only get close to finding the answer and am having trouble putting the concepts together. A lot of what I find is just single files into a new directory, with a rename. I'd like multiple files to single file into new directory with a rename. Cuz that's how I roll :)
So, I found the answer I was looking for.
This SO post was basically the same question with a good answer. Unfortunately it didn't come up when I was creating my question or else you wouldn't be reading this.
There was a slight tweak to my needs. I needed to do it dynamically per module instead of just one compile.js file so my final code is as follows, placed just after my initConfig():
grunt.registerTask("prepareModules", "Finds and prepares modules for concatenation.", function() {
// get all module directories
grunt.file.expand("src/js/modules/*").forEach(function (dir) {
// get the module name from the directory name
var dirName = dir.substr(dir.lastIndexOf('/')+1);
// get the current concat object from initConfig
var concat = grunt.config.get('concat') || {};
// create a subtask for each module, find all src files
// and combine into a single js file per module
concat[dirName] = {
src: [dir + '/**/*.js'],
dest: 'dev/js/modules/' + dirName + '.min.js'
};
// add module subtasks to the concat task in initConfig
grunt.config.set('concat', concat);
});
});
// the default task
grunt.registerTask("default", ["sass", "ngtemplates", "prepareModules", "concat", "uglify", "cssmin"]);
This essentially makes my concat task look like it did when I was hand coding it, but just a little simpler (and scalable!).
concat: {
...
moduleOne: {
src: "src/js/modules/moduleOne/**/*.js",
dest: "dev/js/modules/moduleOne.min.js"
},
moduleTwo:{
src: "src/js/modules/moduleTwo/**/*.js",
dest: "dev/js/modules/moduleTwo.min.js"
}
}
Another deviation I made from the SO post was that I chose not to have prepareModules run concat on it's own when it was done. My default task (which watch is setup to run during dev) still does all my processing.
This leaves me with the following structure, ready for minification into prod/:
| dev
| js
| modules
|-- moduleOne.min.js
|-- moduleTwo.min.js

define build sources list in external file

I am a gruntjs newbie and am trying to write a build for JS frontend. A requirement is set so that all the source files that enter the build process (concatenation, minification) must be defined in an external file:
|-config
|- js.json
|-src
|- js
|- a.js
|- b.js
|- Gruntfile.js
|- package.json
I have simplified the project structure to illustrate the problem. The config/js.json looks like this:
[
"<%=js_dir%>/a.js",
"<%=js_dir%>/b.js"
]
Gruntfile.js looks like this:
module.exports = function(grunt) {
grunt.initConfig({
concat: {
"options": {"separator": ";"},
"build": {
"src": "<%= grunt.template.process(grunt.file.read('./config/js.json'),{data: {js_dir: './src/js'}})%>"
,
"dest": "build/app.js"
}
}
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('default', ['concat']);
};
When I run it an empty output file is made, because the source list is empty:
...
Reading ./config/js.json...OK
Files: [no src] -> build/app.js
Reading ./config/js.json...OK
Writing out...OK
Writing build/app.js...OK
File "build/app.js" created.
Done, without errors.
To verify my logic I dumped the processed sources list by changing the src property like this:
"src": "<%= grunt.file.write('out',grunt.template.process(grunt.file.read('./config/js.json'),{data: {js_dir: './src/js'}}))%>"
The contents of the out file show that template processing logic is valid:
[
".src/js/a.js",
".src/js/b.js"
]
Since the src property accepts a hardcoded JSON array of source files my guess is that the binding of the sources list is done before the templating is done.
The gruntjs verbose output shows the reading of config/js.json before and after the concatenation which confuses me.
I tried rewriting the config/js.json file so that all the JSON array fits in one line but to no avail.
If this can be done, please tell me how. If it can't be done please tell me why.
My environment:
grunt: grunt-cli v0.1.9, grunt v0.4.1
nodejs: v0.11.6-pre
os: Linux localhost 3.2.0-23-generic #36-Ubuntu x86_64 GNU/Linux
The Grunt config will process templates as the config is read. So you dont need an additional grunt.template.process. Assuming config/js.json is valid JSON just do this:
module.exports = function(grunt) {
grunt.initConfig({
js_dir: 'src/js',
concat: {
options: {separator: ";"},
build: {
src: require('./config/js.json'),
dest: "build/app.js"
}
}
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('default', ['concat']);
};
Always remember Gruntfiles are JavaScript and not JSON.

Configure Grunt File Name Matching for Files with Multiple Dots

I just started using grunt, and love it.
I keep running into an issue that seems like it might be pretty common.
Here it is. I have files named so that words after a dot are something like classes. eg:
layout.coffee
layout.blog.coffee
layout.site.coffee
My grunt task is configured to watch these files and translate them to js like this:
coffee:
dev:
files: [
expand: true
cwd: "<%= yeoman.app %>"
src: ["**/*.coffee"]
dest: "<%= yeoman.dev %>"
ext: ".js"
]
The problem, I think, is that using ext makes the target for all three .coffee files the destination file layout.js, which isn't the intention.
Is there a nice way to configure grunt file mapping for filenames with multiple dots?
Right now I have to change my naming convention to use - instead of ., which is a drag :(
Note that there is another option "extDot" that you can use to specify after which dot the ext should apply (first or last):
E.g.
files: [{
expand: true,
src: ['*.js','!*min.js'],
dest: 'js',
cwd: 'js',
ext: '.min.js',
extDot: 'last'
}]
Take a look at the "Building the files object dynamically" section of Configuring Tasks.
Instead of specifying ext, you can specify rename which is a function that lets you create your own mapping for the file names.
The problem you are running into was brought up as an issue on github and the answer from the grunt folks was that the "extension" of a file should be everything after the first "." instead of the last.
Hope that helps you!
That's the workaround I'm using in my projects:
uglify : {
build : {
src : ['**/*.js', '!*.min.js'],
cwd : 'js/',
dest : 'js/',
expand : true,
rename : function (dest, src) {
var folder = src.substring(0, src.lastIndexOf('/'));
var filename = src.substring(src.lastIndexOf('/'), src.length);
filename = filename.substring(0, filename.lastIndexOf('.'));
return dest + folder + filename + '.min.js';
}
}
}
When the filename is like jquery.2.0.3.js then after minifying that it will be jquery.2.0.3.min.js.

Resources