mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-01 13:54:35 +03:00
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:
parent
52e35a282b
commit
6c5fea40ca
47
Gruntfile.js
47
Gruntfile.js
@ -403,24 +403,10 @@ var _ = require('lodash'),
|
|||||||
// ### grunt-contrib-copy
|
// ### grunt-contrib-copy
|
||||||
// Copy files into their correct locations as part of building assets, or creating release zips
|
// Copy files into their correct locations as part of building assets, or creating release zips
|
||||||
copy: {
|
copy: {
|
||||||
jquery: {
|
|
||||||
cwd: 'core/client/bower_components/jquery/dist/',
|
|
||||||
src: 'jquery.js',
|
|
||||||
dest: 'core/built/public/',
|
|
||||||
expand: true,
|
|
||||||
nonull: true
|
|
||||||
},
|
|
||||||
release: {
|
release: {
|
||||||
files: [{
|
expand: true,
|
||||||
cwd: 'core/client/bower_components/jquery/dist/',
|
src: buildGlob,
|
||||||
src: 'jquery.js',
|
dest: '<%= paths.releaseBuild %>/'
|
||||||
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-update-submodules
|
||||||
// Grunt task to update git submodules
|
// Grunt task to update git submodules
|
||||||
update_submodules: {
|
update_submodules: {
|
||||||
@ -920,7 +885,7 @@ var _ = require('lodash'),
|
|||||||
// ### Basic Asset Building
|
// ### Basic Asset Building
|
||||||
// Builds and moves necessary client assets. Prod additionally builds the ember app.
|
// Builds and moves necessary client assets. Prod additionally builds the ember app.
|
||||||
grunt.registerTask('assets', 'Basic asset building & moving',
|
grunt.registerTask('assets', 'Basic asset building & moving',
|
||||||
['clean:tmp', 'buildAboutPage', 'copy:jquery']);
|
['clean:tmp', 'buildAboutPage']);
|
||||||
|
|
||||||
// ### Default asset build
|
// ### Default asset build
|
||||||
// `grunt` - default grunt task
|
// `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.
|
// 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',
|
grunt.registerTask('prod', 'Build JS & templates for production',
|
||||||
['shell:ember:prod', 'uglify:prod', 'master-warn']);
|
['shell:ember:prod', 'master-warn']);
|
||||||
|
|
||||||
// ### Live reload
|
// ### Live reload
|
||||||
// `grunt dev` - build assets on the fly whilst developing
|
// `grunt dev` - build assets on the fly whilst developing
|
||||||
@ -961,7 +926,7 @@ var _ = require('lodash'),
|
|||||||
' - Copy files to release-folder/#/#{version} directory\n' +
|
' - Copy files to release-folder/#/#{version} directory\n' +
|
||||||
' - Clean out unnecessary files (travis, .git*, etc)\n' +
|
' - Clean out unnecessary files (travis, .git*, etc)\n' +
|
||||||
' - Zip files in release-folder to dist-folder/#{version} directory',
|
' - 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;
|
module.exports = configureGrunt;
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
// RESTful API for creating notifications
|
// RESTful API for creating notifications
|
||||||
var Promise = require('bluebird'),
|
var Promise = require('bluebird'),
|
||||||
_ = require('lodash'),
|
_ = require('lodash'),
|
||||||
canThis = require('../permissions').canThis,
|
permissions = require('../permissions'),
|
||||||
errors = require('../errors'),
|
errors = require('../errors'),
|
||||||
utils = require('./utils'),
|
utils = require('./utils'),
|
||||||
pipeline = require('../utils/pipeline'),
|
pipeline = require('../utils/pipeline'),
|
||||||
|
canThis = permissions.canThis,
|
||||||
|
|
||||||
// Holds the persistent notifications
|
// Holds the persistent notifications
|
||||||
notificationsStore = [],
|
notificationsStore = [],
|
||||||
@ -57,6 +58,10 @@ notifications = {
|
|||||||
* @returns {Object} options
|
* @returns {Object} options
|
||||||
*/
|
*/
|
||||||
function handlePermissions(options) {
|
function handlePermissions(options) {
|
||||||
|
if (permissions.parseContext(options.context).internal) {
|
||||||
|
return Promise.resolve(options);
|
||||||
|
}
|
||||||
|
|
||||||
return canThis(options.context).add.notification().then(function () {
|
return canThis(options.context).add.notification().then(function () {
|
||||||
return options;
|
return options;
|
||||||
}, function () {
|
}, function () {
|
||||||
|
@ -9,14 +9,17 @@ var Promise = require('bluebird'),
|
|||||||
sequence = require('../../utils/sequence'),
|
sequence = require('../../utils/sequence'),
|
||||||
_ = require('lodash'),
|
_ = require('lodash'),
|
||||||
errors = require('../../errors'),
|
errors = require('../../errors'),
|
||||||
|
config = require('../../config'),
|
||||||
utils = require('../../utils'),
|
utils = require('../../utils'),
|
||||||
models = require('../../models'),
|
models = require('../../models'),
|
||||||
fixtures = require('./fixtures'),
|
fixtures = require('./fixtures'),
|
||||||
permissions = require('./permissions'),
|
permissions = require('./permissions'),
|
||||||
|
notifications = require('../../api/notifications'),
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
logInfo,
|
logInfo,
|
||||||
to003,
|
to003,
|
||||||
|
to004,
|
||||||
convertAdminToOwner,
|
convertAdminToOwner,
|
||||||
createOwner,
|
createOwner,
|
||||||
options = {context: {internal: true}},
|
options = {context: {internal: true}},
|
||||||
@ -125,7 +128,7 @@ to003 = function () {
|
|||||||
Role = models.Role,
|
Role = models.Role,
|
||||||
Client = models.Client;
|
Client = models.Client;
|
||||||
|
|
||||||
logInfo('Upgrading fixtures');
|
logInfo('Upgrading fixtures to 003');
|
||||||
|
|
||||||
// Add the client fixture if missing
|
// Add the client fixture if missing
|
||||||
upgradeOp = Client.findOne({secret: fixtures.clients[0].secret}).then(function (client) {
|
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) {
|
update = function (fromVersion, toVersion) {
|
||||||
|
var ops = [];
|
||||||
|
|
||||||
logInfo('Updating fixtures');
|
logInfo('Updating fixtures');
|
||||||
// Are we migrating to, or past 003?
|
// Are we migrating to, or past 003?
|
||||||
if ((fromVersion < '003' && toVersion >= '003') ||
|
if ((fromVersion < '003' && toVersion >= '003') ||
|
||||||
fromVersion === '003' && toVersion === '003' && process.env.FORCE_MIGRATION) {
|
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 = {
|
module.exports = {
|
||||||
|
@ -8,21 +8,13 @@
|
|||||||
|
|
||||||
var hbs = require('express-hbs'),
|
var hbs = require('express-hbs'),
|
||||||
_ = require('lodash'),
|
_ = require('lodash'),
|
||||||
config = require('../config'),
|
|
||||||
filters = require('../filters'),
|
filters = require('../filters'),
|
||||||
api = require('../api'),
|
api = require('../api'),
|
||||||
utils = require('./utils'),
|
|
||||||
ghost_foot;
|
ghost_foot;
|
||||||
|
|
||||||
ghost_foot = function (options) {
|
ghost_foot = function (options) {
|
||||||
/*jshint unused:false*/
|
/*jshint unused:false*/
|
||||||
var jquery = utils.isProduction ? 'jquery.min.js' : 'jquery.js',
|
var foot = [];
|
||||||
foot = [];
|
|
||||||
|
|
||||||
foot.push(utils.scriptTemplate({
|
|
||||||
source: config.paths.subdir + '/public/' + jquery,
|
|
||||||
version: config.assetHash
|
|
||||||
}));
|
|
||||||
|
|
||||||
return api.settings.read({key: 'ghost_foot'}).then(function (response) {
|
return api.settings.read({key: 'ghost_foot'}).then(function (response) {
|
||||||
foot.push(response.settings[0].value);
|
foot.push(response.settings[0].value);
|
||||||
|
@ -128,7 +128,11 @@ describe('Tags API', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('Browse', function () {
|
describe('Browse', function () {
|
||||||
beforeEach(testUtils.setup('tags'));
|
beforeEach(function (done) {
|
||||||
|
testUtils.fixtures.insertMoreTags().then(function () {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('can browse (internal)', function (done) {
|
it('can browse (internal)', function (done) {
|
||||||
TagAPI.browse(testUtils.context.internal).then(function (results) {
|
TagAPI.browse(testUtils.context.internal).then(function (results) {
|
||||||
|
40
core/test/integration/migration_spec.js
Normal file
40
core/test/integration/migration_spec.js
Normal 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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -19,85 +19,31 @@ describe('{{ghost_foot}} helper', function () {
|
|||||||
utils.loadHelpers();
|
utils.loadHelpers();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
sandbox = sinon.sandbox.create();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has loaded ghost_foot helper', function () {
|
||||||
|
should.exist(handlebars.helpers.ghost_foot);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('outputs correct injected code', function (done) {
|
||||||
|
sandbox.stub(api.settings, 'read', function () {
|
||||||
|
return Promise.resolve({
|
||||||
|
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 () {
|
afterEach(function () {
|
||||||
sandbox.restore();
|
sandbox.restore();
|
||||||
utils.restoreConfig();
|
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();
|
|
||||||
sandbox.stub(api.settings, 'read', function () {
|
|
||||||
return Promise.resolve({
|
|
||||||
settings: [{value: '<script></script>'}]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -79,7 +79,6 @@
|
|||||||
"grunt-contrib-compress": "0.13.0",
|
"grunt-contrib-compress": "0.13.0",
|
||||||
"grunt-contrib-copy": "0.8.0",
|
"grunt-contrib-copy": "0.8.0",
|
||||||
"grunt-contrib-jshint": "0.11.2",
|
"grunt-contrib-jshint": "0.11.2",
|
||||||
"grunt-contrib-uglify": "0.9.1",
|
|
||||||
"grunt-contrib-watch": "0.6.1",
|
"grunt-contrib-watch": "0.6.1",
|
||||||
"grunt-docker": "0.0.10",
|
"grunt-docker": "0.0.10",
|
||||||
"grunt-express-server": "0.5.1",
|
"grunt-express-server": "0.5.1",
|
||||||
|
Loading…
Reference in New Issue
Block a user