From f98ab5ffebe54800020d26972b1c8a36ef0fe538 Mon Sep 17 00:00:00 2001 From: Mike Horn Date: Thu, 17 Apr 2014 15:56:24 -0700 Subject: [PATCH] back to grunt --- .gitignore | 3 + Gruntfile.js | 7 + api/index.js | 65 +++--- app/index.html | 351 ++++++++++++++++++++++------- app/scripts/app.js | 55 +++-- app/scss/app.scss | 9 + app/templates/compressor.hbs | 50 ++++ bower.json | 6 +- config/environments/development.js | 2 +- grunt/aliases.yaml | 30 +++ grunt/clean.js | 4 + grunt/connect.js | 8 + grunt/copy.js | 8 + grunt/emberTemplates.js | 16 ++ grunt/express.js | 7 + grunt/htmlmin.js | 12 + grunt/jshint.js | 7 + grunt/preprocess.js | 12 + grunt/rev.js | 11 + grunt/sass.js | 12 + grunt/usemin.js | 3 + grunt/useminPrepare.js | 6 + grunt/watch.js | 25 ++ gulpfile.js | 121 ---------- package.json | 42 ++-- 25 files changed, 600 insertions(+), 272 deletions(-) create mode 100644 Gruntfile.js create mode 100644 app/templates/compressor.hbs create mode 100644 grunt/aliases.yaml create mode 100644 grunt/clean.js create mode 100644 grunt/connect.js create mode 100644 grunt/copy.js create mode 100644 grunt/emberTemplates.js create mode 100644 grunt/express.js create mode 100644 grunt/htmlmin.js create mode 100644 grunt/jshint.js create mode 100644 grunt/preprocess.js create mode 100644 grunt/rev.js create mode 100644 grunt/sass.js create mode 100644 grunt/usemin.js create mode 100644 grunt/useminPrepare.js create mode 100644 grunt/watch.js delete mode 100644 gulpfile.js diff --git a/.gitignore b/.gitignore index 82a0bef..595eda1 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ bower_components/ node_modules/ dist/ dev/ +.tmp/ +tmp/ +.sass-cache/ diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..95df3db --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,7 @@ +module.exports = function (grunt) { + // measures the time each task takes + require('time-grunt')(grunt); + + // load grunt config + require('load-grunt-config')(grunt); +}; diff --git a/api/index.js b/api/index.js index 46c1a6d..1b18a12 100644 --- a/api/index.js +++ b/api/index.js @@ -4,12 +4,11 @@ var compress = require('compression')(); var bodyParser = require('body-parser'); var UglifyJS = require('uglify-js'); var CleanCSS = require('clean-css'); -var hljs = require('highlight.js'); var errorhandler = require('errorhandler'); var api = express(); api.use(morgan('dev')); -// api.use(compress); +api.use(compress); api.use(bodyParser({ limit: '1mb' })); api.use(errorhandler()); @@ -33,46 +32,44 @@ api.all('*', function(req, res, next){ next(); }); - -api.post('/', function(req, res){ +api.post('/javascript/', function (req, res) { if (!req.param('code')) { res.send(404, ':('); } - var highlighted = hljs.highlightAuto(req.param('code'), ['javascript', 'css']); - var output = { language: highlighted.language }; - - switch (output.language) { - case 'javascript': - try { - var minified = UglifyJS.minify(req.param('code'), { - fromString: true, - warnings: true, - compress: { - warnings: true - } - }); - output.code = minified.code; - output.map = minified.map; - } catch (error) { - delete error.stack; - res.json(500, error); - } - res.send(output); - break; + try { + output = UglifyJS.minify(req.param('code'), { + fromString: true, + warnings: true, + compress: { + warnings: true + } + }); + } catch (error) { + // users don't need to see filestructure of server + delete error.stack; + res.json(500, error); + } + res.send(output); - case 'css': - output.code = new CleanCSS().minify(req.param('code')); - res.send(output); - break; +}); + +api.post('/css/', function (req, res) { - default: - res.json(500, 'Sorry, we could not figure out what language you are trying to compress.'); + if (!req.param('code')) { + res.send(404, ':('); } + + var output = { + code: new CleanCSS().minify(req.param('code')) + }; + + res.send(output); + }); -api.post('/:fileName', function (req, res) { +api.post('/gz/:fileName', function (req, res) { compress(req, res, function (error) { if (error) { res.json(error); @@ -87,4 +84,6 @@ api.all('*', function (req, res) { res.send(404); }); -api.listen(3001); +api.listen(3000, function() { + console.log('Server listening on port 3000'); +}); diff --git a/app/index.html b/app/index.html index 5a87ed1..f5b3a62 100644 --- a/app/index.html +++ b/app/index.html @@ -1,116 +1,307 @@ - + Refresh-SF - Online JavaScript and CSS Compressor - - - - + + + + + + - - +
+
+
+

FAQs

+
+
+
+
Why did you make this?
+
Not everyone is comfortable with command line interfaces or deployment pipelines. This just makes it easy if you don't have a system set up.
+
Do you make a copy of my code?
+
No. Code entered into this site is not stored anywhere. The source for this site is on GitHub at gpbmike/refresh-sf.

+
+
+
+
- +
December 13, 2009
- - - +
+ +
- - - - - +
May 30, 2009
- - - +
+ +
+
March 10, 2009
+ +
+ +
+ +
January 18, 2009
+ +
+ +
+ +
November 7, 2008
+ +
+ +
+ +
October 7, 2008
+ +
+ +
+ +
October 4, 2008
+ +
+ +
+ +
October 2, 2008
+ +
+ +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/scripts/app.js b/app/scripts/app.js index 9300465..88ae684 100644 --- a/app/scripts/app.js +++ b/app/scripts/app.js @@ -1,7 +1,15 @@ (function () { + 'use strict'; + Ember.throttledObserver = function(func, key, time) { + return Em.observer(function() { + Em.run.throttle(this, func, time); + }, key); + }; + var App = Ember.Application.create({ + rootElement : '#compressor', LOG_ACTIVE_GENERATION : true, LOG_MODULE_RESOLVER : true, LOG_TRANSITIONS : true, @@ -17,18 +25,33 @@ App.CompressorController = Ember.Controller.extend({ - placeholder: 'To get started, paste your JavaScript or CSS code here, or drag in files from your desktop.', + placeholder: 'Paste your JavaScript or CSS code here, or drag in files from your desktop.', apiUrl: window.ENV.apiUrl, + language: null, + languages: ['javascript', 'css'], + gzipUrl: function () { - return this.get('apiUrl') + this.get('filename'); + return this.get('apiUrl') + 'gz/' + this.get('filename'); }.property('apiUrl', 'filename'), saveDisabled: function () { return !this.get('filename'); }.property('filename'), + compressDisabled: function () { + return !this.get('input') || !this.get('language') || this.get('isCompressing'); + }.property('input', 'language', 'isCompressing'), + + checkLanguage: Ember.throttledObserver(function () { + + var highlighted = hljs.highlightAuto(this.get('input'), this.get('languages')); + + this.set('language', highlighted.language); + + }, 'input', 500), + displayLanguage: function () { switch (this.get('language')) { @@ -44,25 +67,22 @@ compress: function () { this.set('output', null); - this.set('language', null); this.set('error', null); this.set('isCompressing', true); return new Ember.RSVP.Promise(function(resolve, reject) { Ember.$.ajax({ - url: this.get('apiUrl'), + url: this.get('apiUrl') + this.get('language') + '/', type: 'post', data: { code: this.get('input') }, dataType: 'json' }).done(function (data) { - this.set('language', data.language); this.set('output', data.code); Ember.run(null, resolve); }.bind(this)).fail(function (jqXHR) { this.set('error', true); - this.set('output', JSON.stringify(jqXHR.responseJSON, null, 2)); - Ember.run(null, reject); + Ember.run(null, reject, JSON.stringify(jqXHR.responseJSON, null, 2)); }.bind(this)).always(function () { this.set('isCompressing', false); }.bind(this)); @@ -73,16 +93,19 @@ compress: function () { this.compress().then(function () { - var filename; + if (this.get('filename')) { + return; + } if (this.get('language') === 'css') { - filename = 'style.min.css'; + this.set('filename', 'style.min.css'); } else { - filename = 'app.min.js'; + this.set('filename', 'app.min.js'); } - this.set('filename', filename); - + }.bind(this), function (error) { + this.set('error', true); + this.set('output', error); }.bind(this)); }, save: function () { @@ -94,7 +117,6 @@ }, clearOutput: function () { this.set('output', null); - this.set('language', null); } } @@ -107,8 +129,13 @@ accept: 'text/*', dragClass: 'dragging', on: { - load: function (event) { + load: function (event, file) { this.set('value', this.getWithDefault('value', '') + event.target.result); + + var filename = file.name.split('.'); + filename.splice(-1, 0, 'min'); + + this.set('parentView.controller.filename', filename.join('.')); }.bind(this), } }); diff --git a/app/scss/app.scss b/app/scss/app.scss index 01390ea..be0b174 100644 --- a/app/scss/app.scss +++ b/app/scss/app.scss @@ -1,3 +1,12 @@ .form-control.input.dragging { background-color: #d9edf7; } + +textarea { + font-family: monospace; +} + +.compressed-actions { + margin-top: 20px; + margin-bottom: 10px; +} diff --git a/app/templates/compressor.hbs b/app/templates/compressor.hbs new file mode 100644 index 0000000..fb4b0bd --- /dev/null +++ b/app/templates/compressor.hbs @@ -0,0 +1,50 @@ +{{#unless output}} + +
+
+

+ {{#unless compressDisabled}} + + {{/unless}} + Input Code +

+
+ {{view App.DragAndDrop value=input class="form-control input" rows="10" placeholder=placeholder disabled=isCompressing}} +
+
+
+ +{{else}} + +
+
+

Compressed {{displayLanguage}}

+
+
+ {{#if error}} + + {{else}} +
+ {{input class="form-control" value=filename}} + + + + + +
+ {{/if}} +
+
+ +
+
+
{{output}}
+
+
+ +{{/unless}} + +{{!-- Hidden form used to POST to gzip url for download --}} +
+ {{input name="code" value=output type="hidden"}} +
diff --git a/bower.json b/bower.json index 23a1485..185b5e3 100644 --- a/bower.json +++ b/bower.json @@ -19,6 +19,10 @@ "filereader.js": "bgrins/filereader.js", "zeroclipboard": "~1.3.5", "FileSaver.js": "eligrey/FileSaver.js", - "handlebars": "~1.3.0" + "handlebars": "~1.3.0", + "jshint": "~2.5.0", + "uglify-js": "mishoo/UglifyJS2", + "clean-css": "GoalSmashers/clean-css", + "requirejs": "~2.1.11" } } diff --git a/config/environments/development.js b/config/environments/development.js index 1de7908..3650cb2 100644 --- a/config/environments/development.js +++ b/config/environments/development.js @@ -1 +1 @@ -window.ENV.apiUrl = 'http://localhost:3001/'; +window.ENV.apiUrl = 'http://localhost:3000/'; diff --git a/grunt/aliases.yaml b/grunt/aliases.yaml new file mode 100644 index 0000000..d6562d1 --- /dev/null +++ b/grunt/aliases.yaml @@ -0,0 +1,30 @@ +default: + - 'serve' + +dev: + - 'jshint' + - 'clean:dev' + - 'sass:dev' + - 'preprocess:dev' + - 'copy:dev' + - 'emberTemplates:dev' + +serve: + - 'dev' + - 'express' + - 'connect:dev' + - 'watch' + +build: + - 'jshint' + - 'clean:dist' + - 'preprocess:dist' + - 'sass:dist' + - 'copy:dist' + - 'emberTemplates:dist' + - 'useminPrepare' + - 'concat' + - 'uglify' + - 'cssmin' + - 'usemin' + - 'htmlmin' diff --git a/grunt/clean.js b/grunt/clean.js new file mode 100644 index 0000000..5c4e67b --- /dev/null +++ b/grunt/clean.js @@ -0,0 +1,4 @@ +module.exports = { + dev: ['./dev'], + dist: ['./dist'] +}; diff --git a/grunt/connect.js b/grunt/connect.js new file mode 100644 index 0000000..2709135 --- /dev/null +++ b/grunt/connect.js @@ -0,0 +1,8 @@ +module.exports = { + dev: { + options: { + base: ['./', './dev'], + livereload: true + } + } +}; diff --git a/grunt/copy.js b/grunt/copy.js new file mode 100644 index 0000000..5959e96 --- /dev/null +++ b/grunt/copy.js @@ -0,0 +1,8 @@ +module.exports = { + dev: { files: [ + { expand: true, cwd: './app/', src: ['scripts/*'], dest: './dev/' } + ] }, + dist: { files: [ + { expand: true, cwd: './app/', src: ['scripts/*'], dest: './tmp/' } + ] } +}; diff --git a/grunt/emberTemplates.js b/grunt/emberTemplates.js new file mode 100644 index 0000000..109f123 --- /dev/null +++ b/grunt/emberTemplates.js @@ -0,0 +1,16 @@ +module.exports = { + options: { + templateBasePath: /app\/templates\// + }, + dev: { + options: { + precompile: false + }, + src: "app/templates/**/*.{hbs,hjs,handlebars}", + dest: "dev/scripts/templates.js" + }, + dist: { + src: "<%= emberTemplates.dev.src %>", + dest: "tmp/scripts/templates.js" + } +}; diff --git a/grunt/express.js b/grunt/express.js new file mode 100644 index 0000000..da73497 --- /dev/null +++ b/grunt/express.js @@ -0,0 +1,7 @@ +module.exports = { + all: { + options: { + script: './api/index.js' + } + } +}; diff --git a/grunt/htmlmin.js b/grunt/htmlmin.js new file mode 100644 index 0000000..6bdbe4e --- /dev/null +++ b/grunt/htmlmin.js @@ -0,0 +1,12 @@ +module.exports = { + dist: { + options: { + removeComments: true, + collapseWhitespace: true + }, + files: [{ + src: './tmp/index.html', + dest: './dist/index.html' + }] + } +}; diff --git a/grunt/jshint.js b/grunt/jshint.js new file mode 100644 index 0000000..aab2252 --- /dev/null +++ b/grunt/jshint.js @@ -0,0 +1,7 @@ +module.exports = { + all: [ + 'Gruntfile.js', + 'grunt/*.js', + 'app/*.js' + ] +}; diff --git a/grunt/preprocess.js b/grunt/preprocess.js new file mode 100644 index 0000000..26ddfe7 --- /dev/null +++ b/grunt/preprocess.js @@ -0,0 +1,12 @@ +module.exports = { + dev: { + options: { context: { dist: false } }, + src: './app/index.html', + dest: './dev/index.html' + }, + dist: { + options: { context: { dist: true } }, + src: './app/index.html', + dest: './tmp/index.html' + } +}; diff --git a/grunt/rev.js b/grunt/rev.js new file mode 100644 index 0000000..7bfe61b --- /dev/null +++ b/grunt/rev.js @@ -0,0 +1,11 @@ +module.exports = { + dist: { + files: { + src: [ + 'dist/scripts/app.min.js', + 'dist/scripts/vendor.min.js', + 'dist/css/app.min.css' + ] + } + } +}; diff --git a/grunt/sass.js b/grunt/sass.js new file mode 100644 index 0000000..9c39540 --- /dev/null +++ b/grunt/sass.js @@ -0,0 +1,12 @@ +module.exports = { + dev: { + files: { + './dev/css/app.css': './app/scss/app.scss' + } + }, + dist: { + files: { + './tmp/css/app.css': './app/scss/app.scss' + } + } +}; diff --git a/grunt/usemin.js b/grunt/usemin.js new file mode 100644 index 0000000..ee7e43c --- /dev/null +++ b/grunt/usemin.js @@ -0,0 +1,3 @@ +module.exports = { + html: './tmp/index.html' +}; diff --git a/grunt/useminPrepare.js b/grunt/useminPrepare.js new file mode 100644 index 0000000..66aeac1 --- /dev/null +++ b/grunt/useminPrepare.js @@ -0,0 +1,6 @@ +module.exports = { + html: './tmp/index.html', + options: { + dest: './dist' + } +}; diff --git a/grunt/watch.js b/grunt/watch.js new file mode 100644 index 0000000..8b7ca58 --- /dev/null +++ b/grunt/watch.js @@ -0,0 +1,25 @@ +module.exports = { + options: { + livereload: true, + }, + css: { + files: './app/**/*.scss', + tasks: ['sass'] + }, + scripts: { + files: './app/**/*.js', + tasks: ['jshint', 'copy:dev'] + }, + html: { + files: './app/**/*.html', + tasks: ['preprocess:dev'] + }, + templates: { + files: './app/**/*.hbs', + tasks: ['emberTemplates:dev'] + }, + express: { + files: './api/**', + tasks: ['express'] + } +}; diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index e34b3ca..0000000 --- a/gulpfile.js +++ /dev/null @@ -1,121 +0,0 @@ -// Load plugins -var gulp = require('gulp'), - sass = require('gulp-sass'), - preprocess = require('gulp-preprocess'), - usemin = require('gulp-usemin'), - rev = require('gulp-rev'), - minifycss = require('gulp-minify-css'), - minifyhtml = require('gulp-minify-html'), - jshint = require('gulp-jshint'), - uglify = require('gulp-uglify'), - clean = require('gulp-clean'), - notify = require('gulp-notify'), - serve = require('gulp-serve'), - spawn = require('child_process').spawn, - http = require('http'), - ecstatic = require('ecstatic'), - refresh = require('gulp-livereload'), - lrserver = require('tiny-lr')(), - node; - -var livereloadport = 35729, - serverport = 3000; - -// Hinting -gulp.task('jshint', function() { - gulp.src('./app/**/*.js') - .pipe(jshint()) - .pipe(jshint.reporter('default')); -}); - -gulp.task('live-reload', function () { - // Set up your livereload server - lrserver.listen(livereloadport); -}); - -// Build Dist -gulp.task('process-as-dist', function () { - return gulp.src('./app/*.html') - .pipe(preprocess({ context: { dist: true } })) - .pipe(usemin({ - css : [minifycss(), rev()], - html: [minifyhtml({ empty: true })], - js : [uglify(), rev()] - })) - .pipe(gulp.dest('./dist')); -}); - -gulp.task('copy-bootstrap-to-dist', function () { - return gulp.src('./bower_components/bootstrap/dist/fonts/*.*') - .pipe(gulp.dest('./dist/fonts')); -}); - -gulp.task('dist', ['process-as-dist', 'copy-bootstrap-to-dist'], function () { - return gulp.src('./dist') - .pipe(refresh(lrserver)); -}); - -gulp.task('serve-dist', ['live-reload'], function () { - // Set up your static fileserver, which serves files in the build dir - http.createServer(ecstatic({ root: __dirname + '/dist' })).listen(serverport); -}); - -gulp.task('sass', function () { - return gulp.src('./src/scss/*.scss') - .pipe(sass()) - .pipe(gulp.dest('./app/css')); -}); - -// Build dev -gulp.task('process-as-dev', function () { - return gulp.src('./app/*.html') - .pipe(preprocess({ context: { dist: false } })) - .pipe(gulp.dest('./dev')) - .pipe(gulp.src('./app/scss/*.scss')) - .pipe(sass()) - .pipe(gulp.dest('./dev/css')); -}); - -gulp.task('copy-bootstrap-to-dev', function () { - return gulp.src('./bower_components/bootstrap/dist/fonts/*.*') - .pipe(gulp.dest('./dev/fonts')); -}); - -gulp.task('dev', ['process-as-dev', 'copy-bootstrap-to-dev']); - -gulp.task('serve-dev', ['live-reload'], function () { - //Set up your static fileserver, which serves files in the build dir - http.createServer(ecstatic({ root: __dirname + '/dev' })).listen(serverport); -}); - - -/** - * $ gulp server - * description: launch the server. If there's a server already running, kill it. - */ -gulp.task('api-server', function() { - if (node) { - node.kill(); - } - node = spawn('node', ['api/index.js'], { stdio: 'inherit' }); - node.on('close', function (code) { - if (code === 8) { - gulp.log('Error detected, waiting for changes...'); - } - }); -}); - -gulp.task('watch', function () { - gulp.watch('./app/**', ['process-as-dev']); - gulp.watch('./api/**', ['api-server']); - gulp.watch('./src/scss/*', ['sass']); -}); - -gulp.task('default', ['sass', 'dev', 'serve-dev', 'api-server', 'watch']); - -// clean up if an error goes unhandled. -process.on('exit', function() { - if (node) { - node.kill(); - } -}); diff --git a/package.json b/package.json index f1e6909..d75a7ba 100644 --- a/package.json +++ b/package.json @@ -19,27 +19,25 @@ "compression": "~1.0.1" }, "devDependencies": { - "gulp": "~3.5.6", - "connect-livereload": "~0.3.2", - "tiny-lr": "0.0.5", - "gulp-notify": "~1.2.4", - "gulp-rename": "~1.2.0", - "gulp-uglify": "~0.2.1", - "gulp-livereload": "~1.2.0", - "gulp-ruby-sass": "~0.4.0", - "gulp-concat": "~2.2.0", - "gulp-jshint": "~1.5.1", - "gulp-clean": "~0.2.4", - "gulp-minify-css": "~0.3.0", - "gulp-autoprefixer": "0.0.6", - "gulp-cache": "~0.1.3", - "gulp-imagemin": "~0.1.5", - "gulp-minify-html": "~0.1.1", - "gulp-rev": "~0.3.1", - "gulp-usemin": "~0.3.3", - "gulp-preprocess": "~1.0.1", - "gulp-serve": "~0.2.0", - "ecstatic": "~0.4.13", - "gulp-sass": "~0.7.1" + "grunt": "~0.4.4", + "time-grunt": "~0.3.1", + "grunt-contrib-jshint": "~0.9.2", + "load-grunt-config": "~0.8.0-beta.1", + "grunt-contrib-sass": "~0.7.3", + "grunt-preprocess": "~4.0.0", + "grunt-contrib-copy": "~0.5.0", + "grunt-contrib-clean": "~0.5.0", + "grunt-contrib-connect": "~0.7.1", + "grunt-express-server": "~0.4.13", + "grunt-contrib-watch": "~0.6.1", + "grunt-usemin": "~2.1.0", + "grunt-contrib-concat": "~0.3.0", + "grunt-contrib-uglify": "~0.4.0", + "grunt-contrib-cssmin": "~0.9.0", + "grunt-contrib-htmlmin": "~0.2.0", + "handlebars": "~1.3.0", + "ember-template-compiler": "~1.5.0-beta.4", + "grunt-ember-templates": "~0.4.20", + "grunt-rev": "~0.1.0" } }