Permalink
Browse files

initial

  • Loading branch information...
0 parents commit 8b1f59ec824064cb015dc76b553296c1a2fde7c3 @gpbmike committed Mar 27, 2014
Showing with 527 additions and 0 deletions.
  1. +4 −0 .gitignore
  2. +1 −0 .jshintrc
  3. +90 −0 api/index.js
  4. +116 −0 app/index.html
  5. +120 −0 app/scripts/app.js
  6. +3 −0 app/scss/app.scss
  7. +24 −0 bower.json
  8. +1 −0 config/environment.js
  9. +1 −0 config/environments/development.js
  10. +1 −0 config/environments/production.js
  11. +121 −0 gulpfile.js
  12. +45 −0 package.json
@@ -0,0 +1,4 @@
+bower_components/
+node_modules/
+dist/
+dev/
@@ -0,0 +1 @@
+{}
@@ -0,0 +1,90 @@
+var express = require('express');
+var morgan = require('morgan');
+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(bodyParser({ limit: '1mb' }));
+api.use(errorhandler());
+
+/**
+ * CORS support.
+ */
+
+api.all('*', function(req, res, next){
+ if (!req.get('Origin')) {
+ return next();
+ }
+
+ // use "*" here to accept any origin
+ res.set('Access-Control-Allow-Origin', '*');
+ res.set('Access-Control-Allow-Methods', 'GET, POST');
+ res.set('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
+
+ if ('OPTIONS' === req.method) {
+ return res.send(200);
+ }
+ next();
+});
+
+
+api.post('/', 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;
+
+ case 'css':
+ output.code = new CleanCSS().minify(req.param('code'));
+ res.send(output);
+ break;
+
+ default:
+ res.json(500, 'Sorry, we could not figure out what language you are trying to compress.');
+ }
+});
+
+api.post('/:fileName', function (req, res) {
+ compress(req, res, function (error) {
+ if (error) {
+ res.json(error);
+ }
+
+ res.attachment(req.param('fileName'));
+ res.end(req.param('code'), 'utf8');
+ });
+});
+
+api.all('*', function (req, res) {
+ res.send(404);
+});
+
+api.listen(3001);
@@ -0,0 +1,116 @@
+<!doctype>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Refresh-SF - Online JavaScript and CSS Compressor</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <!-- build:css css/vendor.css -->
+ <link rel="stylesheet" href="../bower_components/bootstrap/dist/css/bootstrap.min.css">
+ <!-- endbuild -->
+ <!-- build:css css/app.css -->
+ <link rel="stylesheet" href="css/app.css">
+ <!-- endbuild -->
+</head>
+<body>
+
+<script type="text/x-handlebars">
+ <div class="container">
+ <div class="page-header">
+ <h1>Online JavaScript/CSS Compressor</h1>
+ <p class="lead">This is a web interface to compress your JavaScript or CSS. This tool uses <a href="https://github.com/mishoo/UglifyJS2">UglifyJS 2</a> and <a href="https://github.com/GoalSmashers/clean-css">Clean-CSS.</a></p>
+ </div>
+ </div>
+
+ {{outlet}}
+
+ <div class="container" style="text-align: center">
+ <hr>
+ <p>Built by <a href="http://twitter.com/gpbmike">@gpbmike</a> with <a href="http://emberjs.com">Ember</a>, <a href="http://getbootstrap.com/">Bootstrap</a>, and <a href="http://gulpjs.com/">gulp.js</a>.</p>
+ </div>
+
+</script>
+
+<script type="text/x-handlebars" data-template-name="compressor">
+
+ <div class="container">
+
+ {{#unless output}}
+ <div class="row">
+ <div class="col-lg-12">
+ <div class="form-group">
+ <h2>Input Code</h2>
+ {{view App.DragAndDrop value=input class="form-control input" rows="10" placeholder=placeholder disabled=isCompressing}}
+ </div>
+ </div>
+ </div>
+
+ {{#if input}}
+ <div class="col-lg-12">
+ <div class="row"><button type="button" class="btn btn-primary" {{action "compress"}} {{bind-attr disabled=isCompressing}}>Compress</button></div>
+ </div>
+ {{/if}}
+
+ {{else}}
+
+ <div class="row">
+ <div class="col-lg-12">
+ <h2>Compressed {{displayLanguage}}</h2>
+ {{textarea value=output classBinding=":form-control :alert error:alert-danger:alert-success" rows=10}}
+ </div>
+ </div>
+
+ <div class="row">
+
+ <div class="col-lg-4">
+ {{#unless error}}
+ <div class="input-group">
+ {{input class="form-control" value=filename}}
+ <span class="input-group-btn">
+ <button type="button" class="btn btn-primary" {{action "save"}} {{bind-attr disabled=saveDisabled}}>Save As</button>
+ </span>
+ </div>
+ {{/unless}}
+ </div>
+
+ <div class="col-lg-8">
+ <button type="button" class="btn btn-default pull-right" {{action "clearOutput"}}>Reset</button>
+ </div>
+
+ </div>
+
+ {{/unless}}
+
+ {{!-- Hidden form used to POST to gzip url for download --}}
+ <form {{bind-attr action=gzipUrl}} method="post">
+ {{input name="code" value=output type="hidden"}}
+ </form>
+
+ </div>
+
+</script>
+
+<!-- build:js scripts/vendor.js -->
+<script src="../bower_components/jquery/jquery.js"></script>
+<script src="../bower_components/handlebars/handlebars.js"></script>
+
+<!-- @if dist=false -->
+<script src="../bower_components/ember/ember.js"></script>
+<!-- @endif --><!-- @if dist=true -->
+<script src="../bower_components/ember/ember.prod.js"></script>
+<!-- @endif -->
+
+<script src="../bower_components/filereader.js/filereader.js"></script>
+<script src="../bower_components/FileSaver.js/FileSaver.js"></script>
+<!-- endbuild -->
+
+<!-- build:js scripts/app.js -->
+<script src="../config/environment.js"></script>
+<!-- @if dist=false -->
+<script src="../config/environments/development.js"></script>
+<!-- @endif --><!-- @if dist=true -->
+<script src="../config/environments/production.js"></script>
+<!-- @endif -->
+<script src="scripts/app.js"></script>
+<!-- endbuild -->
+
+</body>
@@ -0,0 +1,120 @@
+(function () {
+ 'use strict';
+
+ var App = Ember.Application.create({
+ LOG_ACTIVE_GENERATION : true,
+ LOG_MODULE_RESOLVER : true,
+ LOG_TRANSITIONS : true,
+ LOG_TRANSITIONS_INTERNAL: true,
+ LOG_VIEW_LOOKUPS : true
+ });
+
+ App.Router.map(function() {
+ this.route('compressor', { path: '/' });
+ });
+
+ App.CompressorRoute = Ember.Route.extend();
+
+ App.CompressorController = Ember.Controller.extend({
+
+ placeholder: 'To get started, paste your JavaScript or CSS code here, or drag in files from your desktop.',
+
+ apiUrl: window.ENV.apiUrl,
+
+ gzipUrl: function () {
+ return this.get('apiUrl') + this.get('filename');
+ }.property('apiUrl', 'filename'),
+
+ saveDisabled: function () {
+ return !this.get('filename');
+ }.property('filename'),
+
+ displayLanguage: function () {
+
+ switch (this.get('language')) {
+ case 'javascript':
+ return 'JavaScript';
+ case 'css':
+ return 'CSS';
+ default:
+ return null;
+ }
+
+ }.property('language'),
+
+ 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'),
+ 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);
+ }.bind(this)).always(function () {
+ this.set('isCompressing', false);
+ }.bind(this));
+ }.bind(this));
+ },
+
+ actions: {
+ compress: function () {
+ this.compress().then(function () {
+
+ var filename;
+
+ if (this.get('language') === 'css') {
+ filename = 'style.min.css';
+ } else {
+ filename = 'app.min.js';
+ }
+
+ this.set('filename', filename);
+
+ }.bind(this));
+ },
+ save: function () {
+ var blob = new Blob([this.get('output')], {type: 'text/' + this.get('language') + ';charset=utf-8'});
+ saveAs(blob, this.get('filename'));
+ },
+ saveGzip: function () {
+ Ember.$('form').trigger('submit');
+ },
+ clearOutput: function () {
+ this.set('output', null);
+ this.set('language', null);
+ }
+ }
+
+ });
+
+ // Allow users to drop files into textarea from desktop
+ App.DragAndDrop = Ember.TextArea.extend({
+ didInsertElement: function () {
+ this.$().fileReaderJS({
+ accept: 'text/*',
+ dragClass: 'dragging',
+ on: {
+ load: function (event) {
+ this.set('value', this.getWithDefault('value', '') + event.target.result);
+ }.bind(this),
+ }
+ });
+ }
+ });
+
+ window.App = App;
+
+})();
@@ -0,0 +1,3 @@
+.form-control.input.dragging {
+ background-color: #d9edf7;
+}
@@ -0,0 +1,24 @@
+{
+ "name": "refresh-sf",
+ "version": "0.0.0",
+ "authors": [
+ "Mike Horn <gpbmike@gmail.com>"
+ ],
+ "license": "MIT",
+ "private": true,
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "test",
+ "tests"
+ ],
+ "dependencies": {
+ "ember": "~1.4.0",
+ "bootstrap": "~3.1.1",
+ "filereader.js": "bgrins/filereader.js",
+ "zeroclipboard": "~1.3.5",
+ "FileSaver.js": "eligrey/FileSaver.js",
+ "handlebars": "~1.3.0"
+ }
+}
@@ -0,0 +1 @@
+window.ENV = {};
@@ -0,0 +1 @@
+window.ENV.apiUrl = 'http://localhost:3001/';
@@ -0,0 +1 @@
+window.ENV.apiUrl = 'http://refresh-sf.herokuapp.com/';
Oops, something went wrong.

0 comments on commit 8b1f59e

Please sign in to comment.