Last active
December 27, 2015 03:28
-
-
Save davemo/7259064 to your computer and use it in GitHub Desktop.
wip directory watcher
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Exports an object that defines | |
# * all of the configuration needed by the projects' | |
# * depended-on grunt tasks. | |
# * | |
# * You can find the original parent object in: node_modules/lineman/config/application.coffee | |
path = require "path" | |
grunt = require "grunt" | |
# additional grunt plugins | |
npmTasksToLoad = [ | |
"grunt-batman-templates" | |
"grunt-contrib-sass" | |
"grunt-contrib-copy" | |
"grunt-datauri" | |
"grunt-newer" | |
"grunt-parallel" | |
"grunt-concat-sourcemap" | |
"grunt-contrib-uglify" | |
"grunt-rails-asset-digest" | |
"grunt-grunticon" | |
] | |
appTasks = { | |
common: [ | |
"batman_templates" | |
"datauri" | |
"grunticon" | |
"copy:svgicons" | |
"sass" | |
"newer:coffee" | |
"concat_sourcemap" | |
] | |
dev: [ | |
"copy" | |
"facemelting_mindflaying_watcher_3000" | |
] | |
dist: [ | |
"parallel" | |
"rails_asset_digest" | |
"clean" | |
] | |
} | |
if process.env.LINEMAN_AUTO_WATCH is "true" | |
appTasks.dev.push "watch" | |
unless process.env.NODE_ENV is "production" | |
npmTasksToLoad.push "grunt-contrib-imagemin" | |
module.exports = | |
pkg: grunt.file.readJSON("package.json") | |
# any other grunt tasks / plugins to load | |
loadNpmTasks: npmTasksToLoad | |
# sets up the lineman task lifecycle for admin2 | |
appTasks: appTasks | |
# task configuration targets | |
grunticon: | |
svgicons: | |
options: | |
svgo: true | |
src: "<%= files.svgicons.src_path %>" | |
dest: "<%= files.svgicons.compiled_path %>" | |
cssprefix: "ico-" | |
# shopify branding / logo colors should go here as hex values | |
colors: | |
slate: "#526066" | |
green: "#96bf48" | |
blue: "#469ad1" | |
white: "#ffffff" | |
# designery tasks, not part of any lifecycles, available via `lineman grunt <taskname>` | |
imagemin: | |
all_images: | |
files: [ | |
expand: true | |
src: ["app/assets/batman/admin2/resources/images/**/*.{png,jpg,gif}"] | |
dest: "." | |
] | |
# lifecycle tasks | |
clean: | |
admin: | |
src: ["generated"] | |
timestamps: | |
src: ["generated/timestamps"] | |
newer: | |
options: | |
timestamps: "generated/timestamps" | |
coffee: | |
admin: | |
expand: true | |
cwd: "<%= files.js.admin.src_path %>" | |
src: "**/*.coffee" | |
dest: "<%= files.js.admin.compiled_path %>" | |
ext: ".js" | |
spec: | |
expand: true | |
cwd: "<%= files.spec.src_path %>" | |
src: "**/*.coffee" | |
dest: "<%= files.spec.compiled_path %>" | |
ext: ".js" | |
spec_legacy: | |
expand: true | |
flatten: true | |
src: "<%= files.spec.coffee.legacy_watch %>" | |
dest: "<%= files.spec.compiled_path %>" | |
ext: ".js" | |
# inlines image resources as base64 encoded strings | |
# generates SCSS placeholder selectors, and variables | |
datauri: | |
options: | |
checkFilesize: false | |
variables: | |
options: | |
variables: true | |
classPrefix: "data-icon-" | |
src: "<%= files.datauri.src %>" | |
dest: "<%= files.datauri.variables %>" | |
placeholders: | |
options: | |
classPrefix: "data-icon-" | |
src: "<%= files.datauri.src %>" | |
dest: "<%= files.datauri.placeholders %>" | |
# compiles scss | |
sass: | |
admin: | |
options: | |
bundleExec: true | |
loadPath: ['app/assets/batman/admin2/resources/css'] | |
files: | |
"<%= files.sass.app.compiled %>" : "<%= files.sass.app.src %>" | |
"<%= files.sass.rte.compiled %>" : "<%= files.sass.rte.src %>" | |
"<%= files.sass.print.compiled %>" : "<%= files.sass.print.src %>" | |
# batman template precache | |
batman_templates: | |
options: | |
templateFolder: "app/assets/batman/admin2/html" | |
files: | |
src: "<%= files.batman_views %>" | |
dest: "<%= files.batman_viewstore %>" | |
# concatenated bundles, 1 for vendor, 1 for app+batman template precache | |
concat_sourcemap: | |
options: | |
sourcesContent: true | |
vendor: | |
files: | |
"<%= files.js.vendor.concatenated %>": "<%= files.js.vendor.src %>" | |
admin: | |
files: | |
"<%= files.js.admin.concatenated %>": [ | |
"<%= files.js.admin.compiled_src %>" | |
"<%= files.batman_viewstore %>" | |
] | |
spec: | |
files: | |
"<%= files.spec.concatenated %>": "<%= files.spec.src %>" | |
# minification task for js, only happens in the dist lifecycle | |
uglify: | |
options: | |
sourceMappingURL: (myPath) -> | |
extension = path.extname(myPath) | |
path.basename(myPath, ".min#{extension}") + extension + '.map' | |
admin: | |
options: | |
sourceMapIn: "<%= files.js.admin.sourcemap_in %>" | |
sourceMap: "<%= files.js.admin.sourcemap_out %>" | |
files: | |
"<%= files.js.admin.min %>" : "<%= files.js.admin.concatenated %>" | |
vendor: | |
options: | |
sourceMapIn: "<%= files.js.vendor.sourcemap_in %>" | |
sourceMap: "<%= files.js.vendor.sourcemap_out %>" | |
files: | |
"<%= files.js.vendor.min %>" : "<%= files.js.vendor.concatenated %>" | |
# minification task for css, only happens in the dist lifecycle | |
cssmin: | |
admin: | |
files: | |
"<%= files.sass.app.min %>" : "<%= files.sass.app.compiled %>" | |
"<%= files.sass.rte.min %>" : "<%= files.sass.rte.compiled %>" | |
"<%= files.sass.print.min %>" : "<%= files.sass.print.compiled %>" | |
parallel: | |
minification: | |
tasks: [ | |
{ cmd: './node_modules/lineman/cli.js', args: ['grunt', 'uglify:admin'] } | |
{ cmd: './node_modules/lineman/cli.js', args: ['grunt', 'uglify:vendor'] } | |
{ cmd: './node_modules/lineman/cli.js', args: ['grunt', 'cssmin:admin'] } | |
] | |
rails_asset_digest: | |
compile: | |
files: | |
"<%= files.js.admin.dest %>" : "<%= files.js.admin.min %>" | |
"<%= files.js.vendor.dest %>" : "<%= files.js.vendor.min %>" | |
"<%= files.sass.app.dest %>" : "<%= files.sass.app.min %>" | |
"<%= files.sass.rte.dest %>" : "<%= files.sass.rte.min %>" | |
"<%= files.sass.print.dest %>" : "<%= files.sass.print.min %>" | |
"<%= files.js.admin.sourcemap_out %>" : "<%= files.js.admin.sourcemap_out %>" | |
"<%= files.js.vendor.sourcemap_out %>" : "<%= files.js.vendor.sourcemap_out %>" | |
# dev task to copy assets to rails public folder | |
copy: | |
svgicons: | |
files: | |
"<%= files.svgicons.dest %>" : "<%= files.svgicons.compiled %>" | |
sourcemaps: | |
files: | |
"<%= files.js.admin.sourcemap_out %>" : "<%= files.js.admin.sourcemap_in %>" | |
"<%= files.js.vendor.sourcemap_out %>" : "<%= files.js.vendor.sourcemap_in %>" | |
admin: | |
files: | |
"<%= files.js.admin.dest %>" : "<%= files.js.admin.concatenated %>" | |
vendor: | |
files: | |
"<%= files.js.vendor.dest %>": "<%= files.js.vendor.concatenated %>" | |
css: | |
files: | |
"<%= files.sass.app.dest %>" : "<%= files.sass.app.compiled %>" | |
"<%= files.sass.rte.dest %>" : "<%= files.sass.rte.compiled %>" | |
"<%= files.sass.print.dest %>" : "<%= files.sass.print.compiled %>" | |
# dev lifecycle, listens for file changes and reruns appropriate tasks | |
facemelting_mindflaying_watcher_3000: | |
svgicons: | |
files: ["app/assets/batman/admin2/resources/icons"] | |
tasks: ["grunticon", "copy:svgicons", "sass:admin"] | |
admin: | |
files: [ | |
"app/assets/batman/admin2/bootstrap.coffee" | |
"app/assets/batman/admin2/shopify.js.coffee" | |
"app/assets/batman/admin2/controllers" | |
"app/assets/batman/admin2/views" | |
"app/assets/batman/admin2/html" | |
"app/assets/batman/admin2/models" | |
"app/assets/batman/admin2/helpers" | |
"app/assets/batman/admin2/lib" | |
] | |
tasks: ["newer:coffee:admin", "concat_sourcemap:admin", "copy:admin", "copy:sourcemaps"] | |
batman_views: | |
files: ["app/assets/batman/admin2/html"] | |
tasks: ["batman_templates", "concat_sourcemap:admin", "copy:admin", "copy:sourcemaps"] | |
sass: | |
files: [ | |
"app/assets/batman/admin2/resources/css" | |
"!app/assets/batman/admin2/resources/css/_datauri_placeholders.scss" | |
"!app/assets/batman/admin2/resources/css/_datauri_variables.scss" | |
"!app/assets/batman/admin2/resources/css/_svgicons.scss" | |
] | |
tasks: ["sass:admin", "copy:css"] | |
vendor: | |
files: ["app/assets/batman/admin2/vendor"] | |
tasks: ["concat_sourcemap:vendor", "copy:vendor", "copy:sourcemaps"] | |
spec: | |
files: ["test/javascripts"] | |
tasks: ["newer:coffee:spec", "concat_sourcemap:spec"] | |
spec_legacy: | |
files: [ | |
"app/assets/javascripts/google_instant_buy.js.coffee" | |
"app/assets/javascripts/external/app.js.coffee" | |
] | |
tasks: ["newer:coffee:spec_legacy", "concat_sourcemap:spec"] | |
datauri: | |
files: ["app/assets/batman/admin2/resources/images"] | |
tasks: ['datauri', 'sass:admin', 'copy:css'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports = function(grunt) { | |
var _ = grunt.util._; | |
var fs = require('fs'); | |
grunt.registerTask('facemelting_mindflaying_watcher_3000', 'experimental directory only', function() { | |
var pathTaskMap = {}; | |
var watched = {}; | |
var folders = {}; | |
var intervalId; | |
var taskDone = this.async(); | |
var watchcfg = grunt.config('facemelting_mindflaying_watcher_3000'); | |
var targets = Object.keys(watchcfg).filter(function(key) { | |
return typeof watchcfg[key] !== 'string' && !Array.isArray(watchcfg[key]); | |
}); | |
targets = targets.map(function(target) { | |
// Fail if any required config properties have been omitted. | |
target = ['facemelting_mindflaying_watcher_3000', target]; | |
this.requiresConfig(target.concat('files'), target.concat('tasks')); | |
return grunt.config(target); | |
}, this); | |
var cachePathTaskMappings = function(targets) { | |
_(targets).each(function(target) { | |
_(target.files).each(function(file) { | |
pathTaskMap[file] = target.tasks; | |
}); | |
}); | |
}; | |
cachePathTaskMappings(targets); | |
grunt.log.writeln('Waiting to melt faces...'); | |
var nameArgs = this.nameArgs; | |
var patterns = _.pluck(targets, 'files'); | |
var getFolders = function() { | |
return grunt.file.expand({filter: 'isDirectory', cwd: process.cwd()}, patterns); | |
}; | |
var getFiles = function() { | |
return grunt.file.expand({filter: 'isFile', cwd: process.cwd()}, patterns); | |
}; | |
function walk(path) { | |
var results = []; | |
var list = fs.readdirSync(path); | |
list.forEach(function(file) { | |
file = path + '/' + file; | |
if( !fs.existsSync(file) ) { | |
return; | |
} | |
var stat = fs.statSync(file); | |
if (stat && stat.isDirectory()) { | |
results.push( file ); | |
results = results.concat(walk(file)); | |
} | |
}); | |
return results; | |
} | |
function watch(path) { | |
if(!watched[path]) { | |
watched[path] = fs.watch(path, function() { | |
handleChange(path); | |
}); | |
} | |
} | |
function unwatch(path) { | |
if(watched[path]) { | |
watched[path].close(); | |
delete watched[path]; | |
} | |
} | |
function findClosestPath(path) { | |
keys = Object.keys(pathTaskMap); | |
keys = keys.filter(function (x) { | |
return path.indexOf(x) >= 0; | |
}); | |
return keys[0]; | |
} | |
var handleChange = _.debounce(function (fileOrFolderPath) { | |
grunt.log.ok('changed', fileOrFolderPath); | |
clearInterval(intervalId); | |
Object.keys(watched).forEach(unwatch); | |
if(!pathTaskMap[fileOrFolderPath]) { | |
fileOrFolderPath = findClosestPath(fileOrFolderPath); | |
grunt.log.writeln("watch exists on parent:", fileOrFolderPath); | |
} | |
grunt.log.ok(); | |
grunt.task.run(pathTaskMap[fileOrFolderPath]).mark(); | |
grunt.task.run(nameArgs); | |
taskDone(); | |
}, 250); | |
function addWatches() { | |
getFiles().forEach(function(path) { watch(path); }); | |
getFolders().forEach(function(path) { | |
watch(path); | |
if (!folders[path]) { | |
folders[path] = walk(path); | |
} | |
folders[path].forEach( watch); | |
}); | |
} | |
intervalId = setInterval( function() { | |
addWatches(); | |
}, 200 ); | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment