Running grunt on windows 8 - windows

I am trying to run grunt on an existing project on a windows 8 machine.
I've installed grunt-cli globally,by running:
npm install -g grunt-cli
However when trying to run the project with:
grunt develop
I get this error:
Warning: Unable to write "preview.html" file <Error code: EPERM>. Use --force to continue.
Aborted due to warnings.
Then when running
grunt develop --force
I get this error:
Running "less:css/main.css" <less> task
Fatal error: Unable to write "css/main.css" file <Error code: EPERM>.
Any help you could provide on this would be most helpful,
thanks.
Update 1:
This is my Gruntfile.js
module.exports = function(grunt){
grunt.initConfig({
watch: {
less: {
files: ['**/*.less', '!less/_compiled-main.less'],
tasks: 'less'
},
html: {
files: ['preview-template.html', 'js/**/*.js', 'less/**/*.less', '!less/_compiled-main.less'],
tasks: ['includeSource', 'add-dont-edit-prefix-to-preview-html']
},
wysiwyg: {
files: ['less/wysiwyg.less'],
tasks: 'generate-wysiwyg-styles-js'
}
},
less: {
'css/main.css': 'less/_compiled-main.less',
'css/wysiwyg.css': 'less/wysiwyg.less',
options: {
dumpLineNumbers: 'comments'
}
},
includeSource: {
options: {
templates: {
},
},
dev: {
files: {
'preview.html': 'preview-template.html',
'less/_compiled-main.less': 'less/main.less'
}
}
},
connect: {
server: {
options: {
base: '.',
port: 8000
}
}
}
});
// Css preprocessor
grunt.loadNpmTasks('grunt-contrib-less');
// Watch for file changes and run other grunt tasks on change
grunt.loadNpmTasks('grunt-contrib-watch');
// Includes all js files in preview-template.html and saves as preview.html.
// Includes all less files in main.less and saves as _compiled-main.less
grunt.loadNpmTasks('grunt-include-source');
// Static http server
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.registerTask('generate-wysiwyg-styles-js', function(){
var css = grunt.file.read('css/wysiwyg.css');
css = css.replace(/\n/g, '')
var js = '// This file is generated automatically based on wysiwyg.less - don\' edit it directly!\n';
js += '// It needs to exist in JS form so we can include the CSS in the downloaded saved notes file';
js += "\napp.value('wysiwygStyles', '" + css + "');";
grunt.file.write('js/app/wysiwyg-styles.js', js)
})
grunt.registerTask('add-dont-edit-prefix-to-preview-html', function(){
var file = grunt.file.read('preview.html');
var prefix = '<!-- \n\n\n\n Don\'t edit this file, edit preview-template.html instead.' + new Array(20).join('\n') + ' -->';
file = file.replace('<!doctype html>', '<!doctype html>' + prefix)
grunt.file.write('preview.html', file);
});
grunt.registerTask('build-develop', [
'includeSource',
'less',
'generate-wysiwyg-styles-js',
'add-dont-edit-prefix-to-preview-html'
])
grunt.registerTask('develop', [
'build-develop',
'connect:server',
'watch'
]);
}

Try something like this maybe?
less: {
files: {
'css/main.css': 'less/_compiled-main.less',
'css/wysiwyg.css': 'less/wysiwyg.less'
},
options: {
dumpLineNumbers: 'comments'
}
}
Notice the files addition to the less array after grunt.initConfig
Let me know if it works.

Related

Upload external changes not working with GRUNT

I started using gruntjs today. Created all the required files etc.
Here is my Gruntfile.js:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
options: {
separator: "\n"
},
dist: {
src: ['js/lib/*.js','js/main.js'],
dest: 'js/script.js'
}
},
sass: {
dist: {
options: {
style: 'compressed'
},
files: { // Dictionary of files
'css/style.css': 'css/style.scss' // 'destination': 'source'
}
}
},
uglify: {
options: {
sourceMap : true,
mangle : false
},
my_target: {
files: {
'js/script.min.js': ['js/script.js']
}
}
},
watch: {
css: {
files: ['css/*.scss'],
tasks: ['sass']
},
scripts: {
files: ['js/lib/*.js','js/youtube.js','js/main.js'],
tasks: ['concat', 'uglify']
}
}
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
// Default task(s).
grunt.registerTask('default', ['watch']);
};
and it works fine. But there is one little thing in my PHPstorm (running under osx):
GruntJS really makes the changes but they are not uploaded to the server I'm mapped to. I have the Automatic Upload and 'Upload External Changes' checked but still, nothing happens.
Could you somehow help me?
Thanks in advance!
P.s While using the PHPStorm file watchers (scss watcher), the 'Upload External Changes' was working and the files were uploading to server, but after switching to GruntJS the problem occurred.
BTW, File > Synchronize solves the problem, as it reloads the files and then the 'Upload external changes' works, but that's not a very good solution as it's not automatic.
Also, switching the window probably makes PHPStorm synchronize files and this also helps.
Anyway, I'm in search of better solution..
I was using older (v8) version of PHPStorm.
In PHPStorm 10 Problem is solved !!!

Configurable redirect URL in DocPad

I'm using DocPad to generate system documentation. I am including release notes in the format
http://example.com/releases/1.0
http://example.com/releases/1.1
http://example.com/releases/1.2
http://example.com/releases/1.3
I want to include a link which will redirect to the most recent release.
http://example.com/releases/latest
My question: how do I make a link that will redirect to a relative URL based on configuration? I want this to be easily changeable by a non-programmer.
Update: I've added cleanurls into my docpad.js, similar to example below. (see code below). But using "grunt docpad:generate" seems to skip making the redirect (is this an HTML page?). I've a static site. I also confirmed I'm using the latest cleanurls (2.8.1) in my package.json.
Here's my docpad.js
'use strict';
var releases = require('./releases.json'); // list them as a list, backwards: ["1.3", "1.2", "1.1", "1.0"]
var latestRelease = releases.slice(1,2)[0];
module.exports = {
outPath: 'epicenter/docs/',
templateData: {
site: {
swiftype: {
apiKey: 'XXXX',
resultsUrl: '/epicenter/docs/search.html'
},
ga: 'XXXX'
},
},
collections: {
public: function () {
return this.getCollection('documents').findAll({
relativeOutDirPath: /public.*/, isPage: true
});
}
},
plugins: {
cleanurls: {
simpleRedirects: {'/public/releases/latest': '/public/releases/' + latestRelease}
},
lunr: {
resultsTemplate: 'src/partials/teaser.html.eco',
indexes: {
myIndex: {
collection: 'public',
indexFields: [{
name: 'title',
boost: 10
}, {
name: 'body',
boost: 1
}]
}
}
}
}
};
When I run grunt docpad:generate, my pages get generated, but there is an error near the end:
/data/jenkins/workspace/stage-epicenter-docs/docs/docpad/node_modules/docpad-plugin-cleanurls/node_modules/taskgroup/node_modules/ambi/es6/lib/ambi.js:5
export default function ambi (method, ...args) {
^^^^^^
I can't tell if that's the issue preventing this from running but it seems suspicious.
Providing that your configuration is available to the DocPad Configuration File, you can use the redirect abilities of the cleanurls plugin to accomplish this for both dynamic and static environments.
With a docpad.coffee configuration file, it would look something like this:
releases = require('./releases.json') # ['1.0', '1.1', '1.2', '1.3']
latestRelease = releases.slice(-1)[0]
docpadConfig =
plugins:
cleanurls:
simpleRedirects:
'/releases/latest': '/releases/' + latestRelease
module.exports = docpadConfig

Grunt - pass filename variable from command line

I am struggling to understand how I can pass a partial filename from the grunt command line, in order to run a task (from an installed grunt module) on a particular file.
What I want to be able to do is configure a series of tasks to take filename parameter from the command line.
I've tried reworking the final example on this page http://chrisawren.com/posts/Advanced-Grunt-tooling but I'm kind of stabbing in the dark a bit. Thought someone would have a quick answer.
Here is my Gruntfile:
module.exports = function (grunt) {
grunt.initConfig({
globalConfig: globalConfig,
uglify: {
js: {
options: {
mangle: true
},
files: {
'js/<%= globalConfig.file %>.min.js': ['js/<%= globalConfig.file %>.js']
}
}
},
});
// Load tasks so we can use them
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('go', 'Runs a task on a specified file', function (fileName){
globalConfig.file = fileName;
grunt.task.run('uglify:js');
});
};
I attempt to run it from the command line like this:
grunt go:app
to target js/app.js
I get this error:
Aborted due to warnings.
roberts-mbp:150212 - Grunt Tasks robthwaites$ grunt go:app
Loading "Gruntfile.js" tasks...ERROR
>> ReferenceError: globalConfig is not defined
Warning: Task "go:app" not found. Use --force to continue.
Thanks
you can use grunt.option.
your grunt register task will look like this.
> grunt.option('fileName'); grunt.registerTask('go', 'Runs a task on a
> specified file', function (){
> grunt.task.run('uglify:js');
> });
your grunt configuration will be
module.exports = function (grunt) {
var fileName=grunt.option('fileName');
grunt.initConfig({
uglify: {
js: {
options: {
mangle: true
},
files: {
'js/fileName.min.js': ['js/fileName.js']
}
}
},
});
command to run the task from terminal:
$ grunt go --fileName='xyzfile'
I the end I was able to accomplish what I wanted like this, but not sure if this is a standard way.
What I was failing to do was declare the globalConfig variable globally first, so that I could redefine it from the Terminal as I ran my grunt task.
Here is an example. When working with HTML emails I need to:
Process my sass files to css (grunt-contrib-sass)
Run an autoprefixer on the resulting css (grunt-autoprefixer)
Minify my CSS and remove CSS comments (grunt-contrib-cssmin)
Include my full CSS in a tag the of my html file (using grunt-include-replace)
Finally, run premailer on the file to inline all styles (grunt-premailer)
The point is, if I am working on several different HTMl emails in the same project, I need to be able to run all these tasks on html files one-by-one, as needed. The Gruntfile below allows me to do this.
What this does:
If you enter into terminal grunt It will simply run the sass task, which processes all sass files - no file parameter needed from Terminal.
However, if I wish to run a series of processes on a single html file, I enter grunt process:fileName with fileName being the name of the html file without the .html extension.
You will notice that the only tasks that require the fileName are actually include-replace and premailer. However, I still want to run al the other CSS cleanup tasks prior to targetting my chosen file.
The key is:
Declaring the global variable
Load the globalConfig variables into the grunt.initConfig
Use the grunt variable declaration where needed in your tasks
register your custom task, with the fileName variable being used as a paramater.
Hope that helps someone.
module.exports = function (grunt) {
var globalConfig = {
file: 'index' // this is the default value, for a single project.
}
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// load the globalConfig variables
globalConfig: globalConfig,
sass: {
dev: {
files: [{
expand: true,
cwd: 'scss',
src: ['*.scss'],
dest: 'css',
ext: '.css'
}]
}
},
cssmin: {
options: {
keepSpecialComments: 0,
keepBreaks: true,
advanced: false
},
target: {
files: [{
expand: true,
cwd: 'css',
src: '*.css',
dest: 'css',
ext: '.css'
}]
}
},
autoprefixer: {
css: {
src: "css/*.css"
}
},
includereplace: {
your_target: {
options: {
prefix: '\\/\\* ',
suffix: ' \\*\\/',
},
files: {
'inline/<%= globalConfig.file %>-inline.html': ['<%= globalConfig.file %>.html']
}
}
},
premailer: {
main: {
options: {
verbose: true,
preserveStyles: true,
},
src: 'inline/<%= globalConfig.file %>-inline.html',
dest: 'inline/<%= globalConfig.file %>-inline.html'
}
},
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-autoprefixer');
grunt.loadNpmTasks('grunt-include-replace');
grunt.loadNpmTasks('grunt-premailer');
grunt.registerTask('default', 'sass');
grunt.registerTask('process', 'Runs all processing tasks on a specific file to produce inlined file', function (fileName) {
globalConfig.file = fileName;
grunt.task.run('sass', 'autoprefixer', 'cssmin', 'includereplace', 'premailer');
});
}
EDIT: Obviously at the moment this accepts only one parameter I beleive. In other use cases the grunt.option version above could give more functionality, being able to submit several parameters in one command. I will continue to experiment with grunt.option if I find the need to do this.

How to test browserify project using karma/jasmine

I'm totally new to the concept of testing, and i need one solid example on how to do it in my project:
I have a gulp file goes like this (Not all of it, just the important portions)
gulp.task('bundle', function() {
gulp.src('public/angular-app/main.js')
.pipe(browserify({
debug: true
}))
.pipe(gulp.dest('public/min-js'));
});
This is a slight portion of my main.js:
'use strict';
angular.module('myApp', [
'ui.router',
'ui.bootstrap',
'ngSanitize',
'ngFx',
...
], ['$interpolateProvider',
function($interpolateProvider) {
$interpolateProvider.startSymbol('{{');
$interpolateProvider.endSymbol('}}');
}
])
.config(require('./config/routes'))
.config(require('./config/authInterceptor'))
.run(require('./config/runPhase'))
.run(require('./config/xeditable'))
.controller('homeController', require('./controllers/homeController'))
.controller('modalInstanceCtrl', require('./controllers/modalInstanceCtrl'))
.controller('modalparticipantCtrl',require('./controllers/modalParticipantCtrl'))
.controller('generatorController',require('./controllers/generatorController'))
.controller('navController', require('./controllers/navController'))
.controller('signInController', require('./controllers/signInController'))
.controller('pricingController', require('./controllers/pricingController'))
.controller('howItWorksController',require('./controllers/howItWorks'))
...
Now this is my config file for karma:
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'public/vendor/jquery/dist/jquery.js',
'public/vendor/angular/angular.js',
'public/vendor/angular-mocks/angular-mocks.js',
'public/angular-app/**/*.js',
'test/**/*Spec.js'
],
// list of files to exclude
exclude: [
],
When i run karma with karma start this is what i get:
Uncaught reference error:require is not defined
at root/public/angular-app/main.js
So my question is simple, how can i do tests, for example, on my homeController...
//update
So I updated my test file to this:
describe("An Angularjs test suite",function(){
var target, rootScope;
beforeEach(inject(function($rootScope) {
rootScope = $rootScope;
// Mock everything here
spyOn(rootScope, "$on")
}));
beforeEach(inject(function(homeController) {
target = homeController;
}));
it('should have called rootScope.$on', function(){
expect(rootScope.$on).toHaveBeenCalled();
});
});
and my config file to this:
// list of files / patterns to load in the browser
files: [
'public/vendor/jquery/dist/jquery.js',
'public/vendor/angular/angular.js',
'public/vendor/angular-mocks/angular-mocks.js',
'public/min-js/main.js',
'test/**/*Spec.js'
],
// list of files to exclude
exclude: [
],
browserify: {
watch: true,
debug: true
},
preprocessors: {
'test/*': ['browserify']
},
Still nothing works, first he says 'unknown provider homeControllerProvider',
Now if i delete them lines:
beforeEach(inject(function(homeController) {
target = homeController;
}));
it still gives me error, expected spy $on to be called, How do i fix this?
You need to inform Karma to run Browserify before running tests.
You can add this in your Karma config:
{
browserify: {
watch: true,
debug: true
},
preprocessors: {
'test/*': ['browserify']
}
}
Karma config file reference: http://karma-runner.github.io/0.12/config/configuration-file.html
Or have a look at one of of my projects that uses Karma for testing: smild.

Why do I get "No such file or directory found" for my grunt/Sass/Ruby code?

I created a grunt file to watch and compile my Sass code and JavaScript on save. While this works beautifully on the JavaScript portion, somewhere it is failing when compiling the Sass and can not find the source file to use even if the directory and file name are correctly given.
The error I receive is:
Running 'sass:dist' <sass> task
Errno:ENOENT No such file or directory - Content/site.scss
This is my Grunt file:
module.exports = function(grunt) {
var jsSource = [
'Scripts/jquery-1.10.2.js',
'Scripts/jquery.cookie.js',
'Scripts/respond.1.1.0.js',
'Scripts/jquery-ui-1.10.3.custom.js',
'Scripts/script-compensation.js',
'Scripts/webtrends.load.js'
];
var jsDebug = 'scripts/site.js';
var jsRelease = 'scripts/site.min.js';
var jsWatchFiles = ['Scripts/script-compensation.js'];
var cssWatchFiles = ['Content/*.scss'];
var scssSource = ['Content/site.scss'];
// Project configuration.
grunt.initConfig({
concat: {
application: {
src: jsSource,
dest: jsDebug
}
},
uglify: {
options: {
report: 'min'
},
application: {
src: ['<%= concat.application.dest %>'],
dest: jsRelease
}
},
sass: {
options: {
style: 'expanded'
},
dist: {
files: {
'Content/site.css': scssSource
}
}
},
watch: {
js: {
files: jsWatchFiles,
tasks: ['concat']
},
css: {
files: cssWatchFiles,
tasks: ['sass']
}
}
});
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask("default", function(){
grunt.log.writeln("grunt workflow task list:");
grunt.log.writeln("\tgrunt watch - Watch js and scss");
grunt.log.writeln("\t\tWindows: use 'start /d . grunt watch' for background process");
grunt.log.writeln("\tgrunt debug - Build the debug files");
grunt.log.writeln("\tgrunt release - Build the release files");
});
grunt.registerTask('debug', ['concat']);
grunt.registerTask('release', ['concat', 'uglify']);
};
I think the error is coming from Ruby itself, but I can not be sure. Has anyone run across this and if so what can I do to fix? Any help would be greatly appreciated.
Try using File.expand_path() or giving the full path?

Resources