Skip to content

Instantly share code, notes, and snippets.

@toumorokoshi
Last active May 8, 2018 09:45
Show Gist options
  • Save toumorokoshi/6195934 to your computer and use it in GitHub Desktop.
Save toumorokoshi/6195934 to your computer and use it in GitHub Desktop.
How I use grunt w/ buildout
[buildout]
parts = django python node grunt-dependencies build-statics run test reset-db
eggs = south==0.8
Django==1.5.1
Pillow==2.0.0
markdown==2.3.1
djangorestframework
[django]
recipe = djangorecipe
settings = development
project = project
eggs = ${buildout:eggs}
[python]
recipe = zc.recipe.egg
interpreter = python
eggs = ${buildout:eggs}
[node]
recipe = gp.recipe.node
npms = grunt-cli
scripts = grunt
npm
node
[grunt-dependencies]
recipe = plone.recipe.command
command = ./bin/npm install
update-command = ./bin/npm install
[build-statics]
recipe = plone.recipe.command
command = ./bin/grunt less:development; ./bin/grunt copy:javascript; ./bin/grunt handlebars:compile
update-command = ./bin/grunt less:development; ./bin/grunt copy:javascript; ./bin/grunt handlebars:compile
[test]
recipe = yt.recipe.shell
script = ./bin/django test myproject
name = test
[run]
recipe = yt.recipe.shell
script =
./bin/grunt watch &> gruntwatch.log &
./bin/django runserver
name = run
[reset-db]
recipe = yt.recipe.shell
script = rm test.sqlite;
./bin/django syncdb;
./bin/django loaddata myproject/fixtures/test_data.json
name = reset
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
jshint: {
myproject: {
files: [
{ src: ['myproject/static/source/myproject/js/**/*.js'] }
]
}
},
less: {
development: {
files: [
{
expand: true,
cwd: 'myproject/static/source/myproject/less',
src: '**/*.less',
ext: '.css',
dest: 'myproject/static/build/css/myproject'
}
]
},
production: {
options: {
paths: ['myproject/static/build/myproject/css'],
yuicompress: true
},
files: [{
expand: true,
cwd: 'myproject/static/source/myproject/less',
src: '**/*.less',
ext: '.css',
dest: 'myproject/static/build/myproject/css'
}]
}
},
copy: {
javascript: {
files: [
{
expand: true,
cwd: 'myproject/static/source/js',
src: ['**'],
dest: 'myproject/static/build/js'
},
{
expand: true,
cwd: 'myproject/static/source/myproject/js',
src: ['**'],
dest: 'myproject/static/build/js/myproject'
}
]
},
fonts: {
files: [{
expand: true,
flatten: true,
filter: 'isFile',
cwd: 'myproject/static/source',
src: ['fonts/**'],
dest: 'myproject/static/build/fonts'
}]
},
images: {
files: [
{
expand: true,
cwd: 'myproject/static/source/images/flat',
src: ['**'],
dest: 'myproject/static/build/images/flat'
},
{
expand: true,
cwd: 'myproject/static/source/myproject/images',
src: ['**'],
dest: 'myproject/static/build/images/myproject'
}
]
}
},
watch: {
// we can add an event handler to only compile changed files
less: {
files: ['myproject/static/source/myproject/less/**/*.less'],
tasks: ['less:development'],
options: {
nospawn: true,
event: ['added', 'changed']
}
},
javascript: {
files: ['myproject/static/source/myproject/js/**/*.js'],
tasks: ['copy:javascript'],
options: {
nospawn: true,
event: ['added', 'changed']
}
},
templates: {
files: ['myproject/static/source/myproject/templates/**/*.handlebars'],
tasks: ['handlebars:compile'],
options: {
nospawn: true,
event: ['added', 'changed']
}
}
},
handlebars: {
compile: {
options: {
namespace: false,
amd: true,
processName: function(filename) {
// extract filename and use as key instead of the
// default behavior which uses the full path.
// this only applies if we set namespace to something.
return filename.split('/').pop().slice(0, -11);
}
},
files: [
{
expand: true,
cwd: 'myproject/static/source/myproject/templates',
src: ['**/*.handlebars'],
dest: 'myproject/static/build/js/myproject/templates',
ext: '.js'
}
]
}
},
jasmine: {
myproject: {
src: 'myproject/static/source/myproject/js/**/*.js',
options: {
specs: 'myproject/static/source/myproject/js/tests/unit/*Spec.js'
}
}
},
qunit: {
myproject: {
src: 'myproject/static/source/myproject/js/tests/**/*.html',
options: {
// you can add phantomjs options: https://github.com/ariya/phantomjs/wiki/API-Reference
timeout: 5000,
force: true
}
}
}
});
// Load the plugins required to run tasks
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-handlebars');
grunt.loadNpmTasks('grunt-contrib-jasmine');
grunt.loadNpmTasks('grunt-contrib-qunit');
// Default task. Run with $grunt
grunt.registerTask('default', ['jshint', 'less:development', 'watch']);
// jshint task. Run with $grunt jshint
grunt.registerTask('jshint', ['jshint']);
// less compile task. Run with $grunt less-dev
grunt.registerTask('less-dev', ['less:development']);
// watch less files. Run with $grunt watch-less
grunt.registerTask('watch-less', ['watch:less']);
grunt.registerTask('copy-fonts', ['copy:fonts']);
grunt.registerTask('copy-images', ['copy:images']);
};
@toumorokoshi
Copy link
Author

Note that yt.recipe.shell basically just outputs a shell script at the particular endpoint, and adds it to bin/

e.g. bin/run = the body in the 'script' section, that starts the grunt watcher and starts my django server

I also use plone.recipe.command to build the statics on the first run, which runs the grunt processes on your first buildout, and every subsequent buildout after.

@toumorokoshi
Copy link
Author

I don't know if js tests work for this. Never tried it.

@toumorokoshi
Copy link
Author

This also might require a manual ./bin/npm install, I vaguely recall that not working in here, but don't remember why.

@evocateur
Copy link

Sweet, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment