Remove auto-inclusion of jQuery via ghost_foot

closes #5298
- remove all harcoded instances of jQuery throughout the front-end of the blog
- add migration function to add cdn link to ghost_foot code injection when migrating up from version 003
- migration version bump
This commit is contained in:
Austin Burdine 2015-08-18 09:08:52 -04:00 committed by Hannah Wolfe
parent 52e35a282b
commit 6c5fea40ca
8 changed files with 134 additions and 132 deletions

View File

@ -403,24 +403,10 @@ var _ = require('lodash'),
// ### grunt-contrib-copy
// Copy files into their correct locations as part of building assets, or creating release zips
copy: {
jquery: {
cwd: 'core/client/bower_components/jquery/dist/',
src: 'jquery.js',
dest: 'core/built/public/',
expand: true,
nonull: true
},
release: {
files: [{
cwd: 'core/client/bower_components/jquery/dist/',
src: 'jquery.js',
dest: 'core/built/public/',
expand: true
}, {
expand: true,
src: buildGlob,
dest: '<%= paths.releaseBuild %>/'
}]
}
},
@ -437,27 +423,6 @@ var _ = require('lodash'),
}
},
// ### grunt-contrib-uglify
// Minify concatenated javascript files ready for production
uglify: {
prod: {
options: {
sourceMap: false
},
files: {
'core/built/public/jquery.min.js': 'core/built/public/jquery.js'
}
},
release: {
options: {
sourceMap: false
},
files: {
'core/built/public/jquery.min.js': 'core/built/public/jquery.js'
}
}
},
// ### grunt-update-submodules
// Grunt task to update git submodules
update_submodules: {
@ -920,7 +885,7 @@ var _ = require('lodash'),
// ### Basic Asset Building
// Builds and moves necessary client assets. Prod additionally builds the ember app.
grunt.registerTask('assets', 'Basic asset building & moving',
['clean:tmp', 'buildAboutPage', 'copy:jquery']);
['clean:tmp', 'buildAboutPage']);
// ### Default asset build
// `grunt` - default grunt task
@ -934,7 +899,7 @@ var _ = require('lodash'),
//
// It is otherwise the same as running `grunt`, but is only used when running Ghost in the `production` env.
grunt.registerTask('prod', 'Build JS & templates for production',
['shell:ember:prod', 'uglify:prod', 'master-warn']);
['shell:ember:prod', 'master-warn']);
// ### Live reload
// `grunt dev` - build assets on the fly whilst developing
@ -961,7 +926,7 @@ var _ = require('lodash'),
' - Copy files to release-folder/#/#{version} directory\n' +
' - Clean out unnecessary files (travis, .git*, etc)\n' +
' - Zip files in release-folder to dist-folder/#{version} directory',
['init', 'shell:ember:prod', 'uglify:release', 'clean:release', 'shell:shrinkwrap', 'copy:release', 'compress:release']);
['init', 'shell:ember:prod', 'clean:release', 'shell:shrinkwrap', 'copy:release', 'compress:release']);
};
module.exports = configureGrunt;

View File

@ -2,10 +2,11 @@
// RESTful API for creating notifications
var Promise = require('bluebird'),
_ = require('lodash'),
canThis = require('../permissions').canThis,
permissions = require('../permissions'),
errors = require('../errors'),
utils = require('./utils'),
pipeline = require('../utils/pipeline'),
canThis = permissions.canThis,
// Holds the persistent notifications
notificationsStore = [],
@ -57,6 +58,10 @@ notifications = {
* @returns {Object} options
*/
function handlePermissions(options) {
if (permissions.parseContext(options.context).internal) {
return Promise.resolve(options);
}
return canThis(options.context).add.notification().then(function () {
return options;
}, function () {

View File

@ -9,14 +9,17 @@ var Promise = require('bluebird'),
sequence = require('../../utils/sequence'),
_ = require('lodash'),
errors = require('../../errors'),
config = require('../../config'),
utils = require('../../utils'),
models = require('../../models'),
fixtures = require('./fixtures'),
permissions = require('./permissions'),
notifications = require('../../api/notifications'),
// Private
logInfo,
to003,
to004,
convertAdminToOwner,
createOwner,
options = {context: {internal: true}},
@ -125,7 +128,7 @@ to003 = function () {
Role = models.Role,
Client = models.Client;
logInfo('Upgrading fixtures');
logInfo('Upgrading fixtures to 003');
// Add the client fixture if missing
upgradeOp = Client.findOne({secret: fixtures.clients[0].secret}).then(function (client) {
@ -156,13 +159,61 @@ to003 = function () {
});
};
/**
* Update ghost_foot to include a CDN of jquery if the DB is migrating from
* @return {Promise}
*/
to004 = function () {
var value,
jquery = [
'<!-- You can safely delete this line if your theme does not require jQuery -->\n',
'<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>\n\n'
],
privacyMessage = [
'jQuery has been removed from Ghost core and is now being loaded from the jQuery Foundation\'s CDN.',
'This can be changed or removed in your <strong>Code Injection</strong> settings area.'
];
logInfo('Upgrading fixtures to 004');
return models.Settings.findOne('ghost_foot').then(function (setting) {
if (setting) {
value = setting.attributes.value;
// Only add jQuery if it's not already in there
if (value.indexOf(jquery.join('')) === -1) {
logInfo('Adding jQuery link to ghost_foot');
value = jquery.join('') + value;
return models.Settings.edit({key: 'ghost_foot', value: value}, options).then(function () {
if (_.isEmpty(config.privacy)) {
return Promise.resolve();
}
logInfo(privacyMessage.join(' ').replace(/<\/?strong>/g, ''));
return notifications.add({notifications: [{
type: 'info',
message: privacyMessage.join(' ')
}]}, options);
});
}
}
});
};
update = function (fromVersion, toVersion) {
var ops = [];
logInfo('Updating fixtures');
// Are we migrating to, or past 003?
if ((fromVersion < '003' && toVersion >= '003') ||
fromVersion === '003' && toVersion === '003' && process.env.FORCE_MIGRATION) {
return to003();
ops.push(to003);
}
if (fromVersion < '004' && toVersion === '004' ||
fromVersion === '004' && toVersion === '004' && process.env.FORCE_MIGRATION) {
ops.push(to004);
}
return sequence(ops);
};
module.exports = {

View File

@ -8,21 +8,13 @@
var hbs = require('express-hbs'),
_ = require('lodash'),
config = require('../config'),
filters = require('../filters'),
api = require('../api'),
utils = require('./utils'),
ghost_foot;
ghost_foot = function (options) {
/*jshint unused:false*/
var jquery = utils.isProduction ? 'jquery.min.js' : 'jquery.js',
foot = [];
foot.push(utils.scriptTemplate({
source: config.paths.subdir + '/public/' + jquery,
version: config.assetHash
}));
var foot = [];
return api.settings.read({key: 'ghost_foot'}).then(function (response) {
foot.push(response.settings[0].value);

View File

@ -128,7 +128,11 @@ describe('Tags API', function () {
});
describe('Browse', function () {
beforeEach(testUtils.setup('tags'));
beforeEach(function (done) {
testUtils.fixtures.insertMoreTags().then(function () {
done();
});
});
it('can browse (internal)', function (done) {
TagAPI.browse(testUtils.context.internal).then(function (results) {

View File

@ -0,0 +1,40 @@
/*globals describe, before, beforeEach, afterEach, it */
/*jshint expr:true*/
var testUtils = require('../utils'),
should = require('should'),
migration = require('../../server/data/migration/index'),
Models = require('../../server/models');
describe('Database Migration (special functions)', function () {
before(testUtils.teardown);
afterEach(testUtils.teardown);
describe('004', function () {
beforeEach(testUtils.setup('settings'));
it('should add jQuery to ghost_foot injection setting', function (done) {
Models.Settings.findOne('ghost_foot').then(function (setting) {
should.exist(setting);
should.exist(setting.attributes);
setting.attributes.value.should.equal('');
process.env.FORCE_MIGRATION = true; // force a migration
migration.init().then(function () {
Models.Settings.findOne('ghost_foot').then(function (result) {
var jquery = [
'<!-- You can safely delete this line if your theme does not require jQuery -->\n',
'<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>\n\n'
];
should.exist(result);
should.exist(result.attributes);
result.attributes.value.should.equal(jquery.join(''));
done();
});
});
});
});
});
});

View File

@ -19,85 +19,31 @@ describe('{{ghost_foot}} helper', function () {
utils.loadHelpers();
});
afterEach(function () {
sandbox.restore();
utils.restoreConfig();
helpers.__set__('utils.isProduction', false);
});
describe('without Code Injection', function () {
beforeEach(function () {
sandbox = sinon.sandbox.create();
sandbox.stub(api.settings, 'read', function () {
return Promise.resolve({
settings: [{value: ''}]
});
});
});
it('has loaded ghost_foot helper', function () {
should.exist(handlebars.helpers.ghost_foot);
});
it('outputs correct jquery for development mode', function (done) {
utils.overrideConfig({assetHash: 'abc'});
helpers.ghost_foot.call().then(function (rendered) {
should.exist(rendered);
rendered.string.should.match(/<script src=".*\/public\/jquery.js\?v=abc"><\/script>/);
done();
}).catch(done);
});
it('outputs correct jquery for production mode', function (done) {
utils.overrideConfig({assetHash: 'abc'});
helpers.__set__('utils.isProduction', true);
helpers.ghost_foot.call().then(function (rendered) {
should.exist(rendered);
rendered.string.should.match(/<script src=".*\/public\/jquery.min.js\?v=abc"><\/script>/);
done();
}).catch(done);
});
});
describe('with Code Injection', function () {
beforeEach(function () {
sandbox = sinon.sandbox.create();
it('outputs correct injected code', function (done) {
sandbox.stub(api.settings, 'read', function () {
return Promise.resolve({
settings: [{value: '<script></script>'}]
settings: [{value: '<script type="text/javascript">var test = \'I am a variable!\'</script>'}]
});
});
helpers.ghost_foot.call().then(function (rendered) {
should.exist(rendered);
rendered.string.should.match(/<script type="text\/javascript">var test = 'I am a variable!'<\/script>/);
done();
}).catch(done);
});
afterEach(function () {
sandbox.restore();
});
it('outputs correct jquery for development mode', function (done) {
utils.overrideConfig({assetHash: 'abc'});
helpers.ghost_foot.call().then(function (rendered) {
should.exist(rendered);
rendered.string.should.match(/<script src=".*\/public\/jquery.js\?v=abc"><\/script> <script><\/script>/);
done();
}).catch(done);
});
it('outputs correct jquery for production mode', function (done) {
utils.overrideConfig({assetHash: 'abc'});
helpers.__set__('utils.isProduction', true);
helpers.ghost_foot.call().then(function (rendered) {
should.exist(rendered);
rendered.string.should.match(/<script src=".*\/public\/jquery.min.js\?v=abc"><\/script> <script><\/script>/);
done();
}).catch(done);
});
utils.restoreConfig();
});
});

View File

@ -79,7 +79,6 @@
"grunt-contrib-compress": "0.13.0",
"grunt-contrib-copy": "0.8.0",
"grunt-contrib-jshint": "0.11.2",
"grunt-contrib-uglify": "0.9.1",
"grunt-contrib-watch": "0.6.1",
"grunt-docker": "0.0.10",
"grunt-express-server": "0.5.1",