Merge pull request #730 from jgable/gruntClientFiles

Compile assets with grunt
This commit is contained in:
Hannah Wolfe 2013-09-16 01:57:08 -07:00
commit 1ee0d51660
8 changed files with 207 additions and 76 deletions

3
.gitignore vendored
View File

@ -46,3 +46,6 @@ CHANGELOG.md
/core/test/functional/*.png
config.js
# Built asset files
/core/built

View File

@ -40,6 +40,16 @@ var path = require('path'),
files: ['<%= paths.adminAssets %>/sass/**/*'],
tasks: ['sass:admin']
},
concat: {
files: [
'core/client/*.js',
'core/client/helpers/*.js',
'core/client/models/*.js',
'core/client/tpl/*.js',
'core/client/views/*.js'
],
tasks: ['concat']
},
livereload: {
files: [
// Theme CSS
@ -49,11 +59,7 @@ var path = require('path'),
// Admin CSS
'<%= paths.adminAssets %>/css/*.css',
// Admin JS
'core/client/*.js',
'core/client/helpers/*.js',
'core/client/models/*.js',
'core/client/tpl/*.js',
'core/client/views/*.js'
'core/built/scripts/*.js'
],
options: {
livereload: true
@ -343,6 +349,122 @@ var path = require('path'),
tagMessage: '<%= buildType %> Release %VERSION%',
pushTo: "origin build"
}
},
concat: {
dev: {
files: {
"core/built/scripts/vendor.js": [
"core/shared/vendor/jquery/jquery.js",
"core/shared/vendor/jquery/jquery-ui-1.10.3.custom.min.js",
"core/client/assets/lib/jquery-utils.js",
"core/client/assets/lib/uploader.js",
"core/shared/vendor/underscore.js",
"core/shared/vendor/backbone/backbone.js",
"core/shared/vendor/handlebars/handlebars-runtime.js",
"core/shared/vendor/moment.js",
"core/client/assets/vendor/icheck/jquery.icheck.min.js",
"core/shared/vendor/jquery/jquery.ui.widget.js",
"core/shared/vendor/jquery/jquery.iframe-transport.js",
"core/shared/vendor/jquery/jquery.fileupload.js",
"core/client/assets/vendor/codemirror/codemirror.js",
"core/client/assets/vendor/codemirror/addon/mode/overlay.js",
"core/client/assets/vendor/codemirror/mode/markdown/markdown.js",
"core/client/assets/vendor/codemirror/mode/gfm/gfm.js",
"core/client/assets/vendor/showdown/showdown.js",
"core/client/assets/vendor/showdown/extensions/ghostdown.js",
"core/shared/vendor/showdown/extensions/github.js",
"core/client/assets/vendor/shortcuts.js",
"core/client/assets/vendor/validator-client.js",
"core/client/assets/vendor/countable.js",
"core/client/assets/vendor/to-title-case.js",
"core/client/assets/vendor/packery.pkgd.min.js",
"core/client/assets/vendor/jquery.hammer.min.js"
],
"core/built/scripts/helpers.js": [
"core/client/init.js",
"core/client/mobile-interactions.js",
"core/client/toggle.js",
"core/client/markdown-actions.js",
"core/client/helpers/index.js"
],
"core/built/scripts/templates.js": [
"core/client/tpl/hbs-tpl.js"
],
"core/built/scripts/models.js": [
"core/client/models/**/*.js"
],
"core/built/scripts/views.js": [
"core/client/views/**/*.js",
"core/client/router.js"
]
}
},
prod: {
files: {
"core/built/scripts/ghost.js": [
"core/shared/vendor/jquery/jquery.js",
"core/shared/vendor/jquery/jquery-ui-1.10.3.custom.min.js",
"core/client/assets/lib/jquery-utils.js",
"core/client/assets/lib/uploader.js",
"core/shared/vendor/underscore.js",
"core/shared/vendor/backbone/backbone.js",
"core/shared/vendor/handlebars/handlebars-runtime.js",
"core/shared/vendor/moment.js",
"core/client/assets/vendor/icheck/jquery.icheck.min.js",
"core/shared/vendor/jquery/jquery.ui.widget.js",
"core/shared/vendor/jquery/jquery.iframe-transport.js",
"core/shared/vendor/jquery/jquery.fileupload.js",
"core/client/assets/vendor/codemirror/codemirror.js",
"core/client/assets/vendor/codemirror/addon/mode/overlay.js",
"core/client/assets/vendor/codemirror/mode/markdown/markdown.js",
"core/client/assets/vendor/codemirror/mode/gfm/gfm.js",
"core/client/assets/vendor/showdown/showdown.js",
"core/client/assets/vendor/showdown/extensions/ghostdown.js",
"core/shared/vendor/showdown/extensions/github.js",
"core/client/assets/vendor/shortcuts.js",
"core/client/assets/vendor/validator-client.js",
"core/client/assets/vendor/countable.js",
"core/client/assets/vendor/to-title-case.js",
"core/client/assets/vendor/packery.pkgd.min.js",
"core/client/assets/vendor/jquery.hammer.min.js",
"core/client/init.js",
"core/client/mobile-interactions.js",
"core/client/toggle.js",
"core/client/markdown-actions.js",
"core/client/helpers/index.js",
"core/client/tpl/hbs-tpl.js",
"core/client/models/**/*.js",
"core/client/views/**/*.js",
"core/client/router.js"
]
}
}
},
uglify: {
prod: {
files: {
"core/built/scripts/ghost.min.js": "core/built/scripts/ghost.js"
}
}
}
};
@ -654,6 +776,8 @@ var path = require('path'),
"shell:bourbon",
"sass:admin",
"handlebars",
"concat",
"uglify",
"bump:build",
"updateCurrentPackageInfo",
"changelog",
@ -666,6 +790,8 @@ var path = require('path'),
"shell:bourbon",
"sass:admin",
"handlebars",
"concat",
"uglify",
"bump:build",
"updateCurrentPackageInfo",
"changelog",
@ -677,6 +803,8 @@ var path = require('path'),
"shell:bourbon",
"sass:admin",
"handlebars",
"concat",
"uglify",
"changelog",
"copy:build",
"compress:build"
@ -692,7 +820,7 @@ var path = require('path'),
// Prepare the project for development
// TODO: Git submodule init/update (https://github.com/jaubourg/grunt-update-submodules)?
grunt.registerTask("init", ["shell:bourbon", "sass:admin", 'handlebars']);
grunt.registerTask("init", ["shell:bourbon", "default"]);
// Run unit tests
grunt.registerTask("test-unit", ['setTestEnv', 'loadConfig', "mochacli:all"]);
@ -706,8 +834,10 @@ var path = require('path'),
// Generate Docs
grunt.registerTask("docs", ["groc"]);
// TODO: Production build task that minifies with uglify:prod
// When you just say "grunt"
grunt.registerTask("default", ['sass:admin', 'handlebars']);
grunt.registerTask("default", ['sass:admin', 'handlebars', 'concat']);
};
module.exports = configureGrunt;

View File

@ -220,4 +220,4 @@ shortcut = {
else if(ele.removeEventListener) ele.removeEventListener(type, callback, false);
else ele['on'+type] = false;
}
}
};

View File

@ -2,7 +2,7 @@
// Defines core methods required to build the application
// Module dependencies
var config = require('./../config'),
var config = require('../config'),
when = require('when'),
express = require('express'),
errors = require('./server/errorHandling'),
@ -340,11 +340,28 @@ Ghost.prototype.initPlugins = function (pluginsToLoad) {
// Initialise Theme or admin
Ghost.prototype.initTheme = function (app) {
var self = this,
hbsOptions;
oneYear = 31536000000;
app.set('view engine', 'hbs');
// return the correct mime type for woff files
express['static'].mime.define({'application/font-woff': ['woff']});
// Serve the assets of the current theme
app.use(express['static'](self.paths().activeTheme));
// Serve shared assets and images
app.use('/shared', express['static'](path.join(__dirname, '/shared')));
app.use('/content/images', express['static'](path.join(__dirname, '/../content/images')));
// Serve our built scripts; can't use /scripts here because themes already are
app.use("/built/scripts", express['static'](path.join(__dirname, '/built/scripts'), {
// Put a maxAge of one year on built scripts
maxAge: oneYear
}));
return function initTheme(req, res, next) {
app.set('view engine', 'hbs');
// return the correct mime type for woff files
express['static'].mime.define({'application/font-woff': ['woff']});
var hbsOptions;
if (!res.isAdmin) {
@ -369,9 +386,7 @@ Ghost.prototype.initTheme = function (app) {
app.use('/public', express['static'](path.join(__dirname, '/client/assets')));
app.use('/public', express['static'](path.join(__dirname, '/client')));
}
app.use(express['static'](self.paths().activeTheme));
app.use('/shared', express['static'](path.join(__dirname, '/shared')));
app.use('/content/images', express['static'](path.join(__dirname, '/../content/images')));
next();
};
};

View File

@ -3,13 +3,17 @@ var _ = require('underscore'),
downsize = require('downsize'),
when = require('when'),
hbs = require('express-hbs'),
packageInfo = require('../../../package.json'),
errors = require('../errorHandling'),
models = require('../models'),
coreHelpers;
coreHelpers = function (ghost) {
var paginationHelper;
var paginationHelper,
scriptTemplate = _.template("<script src='/built/scripts/<%= name %>?v=<%= version %>'></script>"),
isProduction = process.env.NODE_ENV === "production",
version = encodeURIComponent(packageInfo.version);
/**
* [ description]
@ -317,6 +321,32 @@ coreHelpers = function (ghost) {
return ret;
});
// A helper for inserting the javascript tags with version hashes
ghost.registerThemeHelper("ghostScriptTags", function () {
var scriptFiles = [];
if (isProduction) {
scriptFiles.push("ghost.min.js");
} else {
scriptFiles = [
"vendor.js",
"helpers.js",
"templates.js",
"models.js",
"views.js"
];
}
scriptFiles = _.map(scriptFiles, function (fileName) {
return scriptTemplate({
name: fileName,
version: version
});
});
return scriptFiles.join("");
});
// ## Template driven helpers
// Template driven helpers require that their template is loaded before they can be registered.

View File

@ -36,63 +36,10 @@
<aside id="modal-container">
</aside>
<script src="/shared/vendor/jquery/jquery.js"></script>
<script src="/shared/vendor/jquery/jquery-ui-1.10.3.custom.min.js"></script>
<script src="/public/lib/jquery-utils.js"></script>
<script src="/shared/vendor/underscore.js"></script>
<script src="/shared/vendor/backbone/backbone.js"></script>
<script src="/shared/vendor/handlebars/handlebars-runtime.js"></script>
<script src="/shared/vendor/moment.js"></script>
{{{ghostScriptTags}}}
<script src="/public/vendor/icheck/jquery.icheck.min.js"></script>
<script src="/shared/vendor/jquery/jquery.ui.widget.js"></script>
<script src="/shared/vendor/jquery/jquery.iframe-transport.js"></script>
<script src="/shared/vendor/jquery/jquery.fileupload.js"></script>
<script src="/public/vendor/codemirror/codemirror.js"></script>
<script src="/public/vendor/codemirror/addon/mode/overlay.js"></script>
<script src="/public/vendor/codemirror/mode/markdown/markdown.js"></script>
<script src="/public/vendor/codemirror/mode/gfm/gfm.js"></script>
<script src="/public/vendor/showdown/showdown.js"></script>
<script src="/public/vendor/showdown/extensions/ghostdown.js"></script>
<script src="/shared/vendor/showdown/extensions/github.js"></script>
<script src="/public/vendor/shortcuts.js"></script>
<script src="/public/vendor/validator-client.js"></script>
<script src="/public/vendor/countable.js"></script>
<script src="/public/vendor/to-title-case.js"></script>
<script src="/public/vendor/packery.pkgd.min.js"></script>
<script src="/public/vendor/jquery.hammer.min.js"></script>
<script src="/public/init.js"></script>
<script src="/public/assets/lib/uploader.js"></script>
<script src="/public/tpl/hbs-tpl.js"></script>
<script src="/public/mobile-interactions.js"></script>
<script src="/public/toggle.js"></script>
<script src="/public/markdown-actions.js"></script>
<script src="/public/helpers/index.js"></script>
<!-- // require '/public/models/*' -->
<script src="/public/models/post.js"></script>
<script src="/public/models/user.js"></script>
<script src="/public/models/tag.js"></script>
<script src="/public/models/widget.js"></script>
<script src="/public/models/settings.js"></script>
<script src="/public/models/uploadModal.js"></script>
<!-- // require '/public/views/*' -->
<script src="/public/views/base.js"></script>
<script src="/public/views/post-settings.js"></script>
<script src="/public/models/uploadModal.js"></script>
<script src="/public/views/blog.js"></script>
<script src="/public/views/editor.js"></script>
<script src="/public/views/editor-tag-widget.js"></script>
<script src="/public/views/login.js"></script>
<script src="/public/views/settings.js"></script>
<script src="/public/views/debug.js"></script>
<script src="/public/router.js"></script>
{{{block "bodyScripts"}}}
<script>
Ghost.init();
</script>

View File

@ -90,7 +90,8 @@ describe('Admin Controller', function() {
});
it('should send correct path to image when today is in Sep 2013', function(done) {
clock = sinon.useFakeTimers(1378585460681); // Sat Sep 07 2013 21:24:20 GMT+0100 (BST)
// Sat Sep 07 2013 21:24
clock = sinon.useFakeTimers(new Date(2013, 8, 7, 21, 24).getTime());
sinon.stub(res, 'send', function(data) {
data.should.equal('/content/images/2013/Sep/IMAGE.jpg');
return done();
@ -100,7 +101,8 @@ describe('Admin Controller', function() {
});
it('should send correct path to image when today is in Jan 2014', function(done) {
clock = sinon.useFakeTimers(1388707200000); // Wed Jan 03 2014 00:00:00 GMT+0000 (GMT)
// Jan 1 2014 12:00
clock = sinon.useFakeTimers(new Date(2014, 0, 1, 12).getTime());
sinon.stub(res, 'send', function(data) {
data.should.equal('/content/images/2014/Jan/IMAGE.jpg');
return done();
@ -110,7 +112,8 @@ describe('Admin Controller', function() {
});
it('can upload two different images with the same name without overwriting the first', function(done) {
clock = sinon.useFakeTimers(1378634224614); // Sun Sep 08 2013 10:57:04 GMT+0100 (BST)
// Sun Sep 08 2013 10:57
clock = sinon.useFakeTimers(new Date(2013, 8, 8, 10, 57).getTime());
fs.exists.withArgs('content/images/2013/Sep/IMAGE.jpg').yields(true);
fs.exists.withArgs('content/images/2013/Sep/IMAGE-1.jpg').yields(false);
@ -123,7 +126,8 @@ describe('Admin Controller', function() {
});
it('can upload five different images with the same name without overwriting the first', function(done) {
clock = sinon.useFakeTimers(1378634224614); // Sun Sep 08 2013 10:57:04 GMT+0100 (BST)
// Sun Sep 08 2013 10:57
clock = sinon.useFakeTimers(new Date(2013, 8, 8, 10, 57).getTime());
fs.exists.withArgs('content/images/2013/Sep/IMAGE.jpg').yields(true);
fs.exists.withArgs('content/images/2013/Sep/IMAGE-1.jpg').yields(true);
fs.exists.withArgs('content/images/2013/Sep/IMAGE-2.jpg').yields(true);

View File

@ -41,6 +41,8 @@
"grunt-bump": "~0.0.11",
"grunt-contrib-copy": "~0.4.1",
"grunt-contrib-compress": "~0.5.2",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-uglify": "~0.2.4",
"grunt-groc": "~0.3.0",
"grunt-mocha-cli": "~1.0.6",
"grunt-express-server": "~0.4.2",