0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-04 02:01:58 -05:00

Get Ember Admin ready for production

Closes #3161
- Add a config.js file for the client which is used to configure
  Ember.Application during runtime. The correct version of config.js
  is copied into place by grunt via the copy:(dev|prod) task from
  either config-dev.js or config-prod.js.
- Serve minified and production versions of libraries where applicable
  including handlebars-runtime and ember-prod.
- Bundle third party libraries into vendor.min.js.
- Bundle Ghost's Ember app and templates into ghost.min.js
- Remove all fixture data and code from the client.
This commit is contained in:
Jason Williams 2014-07-17 22:34:21 +00:00
parent a620e9017e
commit 7ae48f1dd3
19 changed files with 137 additions and 4956 deletions

1
.gitignore vendored
View file

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

View file

@ -22,6 +22,8 @@ core/server/data/export/exported*
.jshintrc
*.iml
config.js
core/client/config-dev.js
core/client/config-prod.js
CONTRIBUTING.md
SECURITY.md
.travis.yml

View file

@ -66,7 +66,7 @@ var path = require('path'),
},
ember: {
files: ['core/client/**/*.js'],
tasks: ['clean:tmp', 'transpile', 'concat_sourcemap']
tasks: ['clean:tmp', 'transpile', 'concat_sourcemap:dev']
},
'ghost-ui': {
files: [
@ -253,9 +253,24 @@ var path = require('path'),
}
},
files: {
'core/built/scripts/templates-ember.js': 'core/client/templates/**/*.hbs'
'core/built/scripts/templates-dev.js': 'core/client/templates/**/*.hbs'
}
}
},
prod: {
options: {
templateBasePath: /core\/client\//,
templateFileExtensions: /\.hbs/,
templateRegistration: function (name, template) {
return grunt.config.process('define(\'ghost/') +
name + '\', [\'exports\'], function(__exports__){ __exports__[\'default\'] = ' +
template + '; });';
}
},
files: {
'core/built/scripts/templates.js': 'core/client/templates/**/*.hbs'
}
},
},
// ### grunt-es6-module-transpiler
@ -269,18 +284,26 @@ var path = require('path'),
files: [{
expand: true,
cwd: 'core/client/',
src: ['**/*.js', '!loader.js'],
src: ['**/*.js', '!loader.js', '!config-*.js'],
dest: '.tmp/ember-transpiled/'
}]
}
},
// ### grunt-es6-module-transpiler
// Compiles Ember es6 modules
// ### grunt-concat-sourcemap
// Concatenates transpiled ember app
concat_sourcemap: {
client: {
dev: {
src: ['.tmp/ember-transpiled/**/*.js', 'core/client/loader.js'],
dest: 'core/built/scripts/ghost-dev-ember.js',
dest: 'core/built/scripts/ghost-dev.js',
options: {
sourcesContent: true
}
},
prod: {
src: ['.tmp/ember-transpiled/**/*.js', 'core/built/scripts/templates.js',
'core/client/loader.js'],
dest: 'core/built/scripts/ghost.js',
options: {
sourcesContent: true
}
@ -333,6 +356,9 @@ var path = require('path'),
src: ['**'],
dest: 'core/client/assets/',
expand: true
}, {
src: 'core/client/config-dev.js',
dest: 'core/client/config.js'
}]
},
prod: {
@ -346,6 +372,9 @@ var path = require('path'),
src: ['**'],
dest: 'core/client/assets/',
expand: true
}, {
src: 'core/client/config-prod.js',
dest: 'core/client/config.js'
}]
},
release: {
@ -385,7 +414,7 @@ var path = require('path'),
concat: {
'dev': {
nonull: true,
dest: 'core/built/scripts/vendor-ember.js',
dest: 'core/built/scripts/vendor-dev.js',
src: [
'bower_components/loader.js/loader.js',
'bower_components/jquery/dist/jquery.js',
@ -412,6 +441,40 @@ var path = require('path'),
'bower_components/ember-simple-auth/ember-simple-auth.js',
'bower_components/ember-simple-auth/ember-simple-auth-oauth2.js',
'core/shared/lib/showdown/extensions/ghostimagepreview.js',
'core/shared/lib/showdown/extensions/ghostgfm.js'
]
},
'prod': {
nonull: true,
dest: 'core/built/scripts/vendor.js',
src: [
'bower_components/loader.js/loader.js',
'bower_components/jquery/dist/jquery.js',
'bower_components/lodash/dist/lodash.js',
'bower_components/handlebars/handlebars.runtime.js',
'bower_components/ember/ember.prod.js',
'bower_components/ember-data/ember-data.prod.js',
'bower_components/ember-resolver/dist/ember-resolver.js',
'bower_components/ic-ajax/dist/globals/main.js',
'bower_components/ember-load-initializers/ember-load-initializers.js',
'bower_components/validator-js/validator.js',
'bower_components/codemirror/lib/codemirror.js',
'bower_components/codemirror/addon/mode/overlay.js',
'bower_components/codemirror/mode/markdown/markdown.js',
'bower_components/codemirror/mode/gfm/gfm.js',
'bower_components/showdown/src/showdown.js',
'bower_components/moment/moment.js',
'bower_components/keymaster/keymaster.js',
'bower_components/device/lib/device.js',
'bower_components/jquery-ui/ui/jquery-ui.js',
'bower_components/jquery-file-upload/js/jquery.fileupload.js',
'bower_components/fastclick/lib/fastclick.js',
'bower_components/nprogress/nprogress.js',
'bower_components/ember-simple-auth/ember-simple-auth.js',
'bower_components/ember-simple-auth/ember-simple-auth-oauth2.js',
'core/shared/lib/showdown/extensions/ghostimagepreview.js',
'core/shared/lib/showdown/extensions/ghostgfm.js'
]
@ -422,8 +485,13 @@ var path = require('path'),
// Minify concatenated javascript files ready for production
uglify: {
prod: {
options: {
sourceMap: true,
},
files: {
'core/built/public/jquery.min.js': 'core/built/public/jquery.js'
'core/built/public/jquery.min.js': 'core/built/public/jquery.js',
'core/built/scripts/vendor.min.js': 'core/built/scripts/vendor.js',
'core/built/scripts/ghost.min.js': 'core/built/scripts/ghost.js'
}
}
},
@ -739,9 +807,13 @@ var path = require('path'),
// ### Ember Build *(Utility Task)*
// All tasks related to building the Ember client code including transpiling ES6 modules and building templates
grunt.registerTask('emberBuild', 'Build Ember JS & templates for development',
['clean:tmp', 'emberTemplates:dev', 'transpile', 'concat_sourcemap']);
grunt.registerTask('emberBuildDev', 'Build Ember JS & templates for development',
['clean:tmp', 'emberTemplates:dev', 'transpile', 'concat_sourcemap:dev']);
// ### Ember Build *(Utility Task)*
// All tasks related to building the Ember client code including transpiling ES6 modules and building templates
grunt.registerTask('emberBuildProd', 'Build Ember JS & templates for production',
['clean:tmp', 'emberTemplates:prod', 'transpile', 'concat_sourcemap:prod']);
// ### Init assets
// `grunt init` - will run an initial asset build for you
@ -762,7 +834,7 @@ var path = require('path'),
//
// 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',
['concat', 'uglify', 'copy:prod', 'master-warn']);
['concat:prod', 'copy:prod', 'emberBuildProd', 'uglify', 'master-warn']);
// ### Default asset build
// `grunt` - default grunt task
@ -770,7 +842,7 @@ var path = require('path'),
// Compiles concatenates javascript files for the admin UI into a handful of files instead
// of many files, and makes sure the bower dependencies are in the right place.
grunt.registerTask('default', 'Build JS & templates for development',
['concat', 'copy:dev', 'emberBuild']);
['concat:dev', 'copy:dev', 'emberBuildDev']);
// ### Live reload
// `grunt dev` - build assets on the fly whilst developing
@ -784,7 +856,7 @@ var path = require('path'),
//
// Note that the current implementation of watch only works with casper, not other themes.
grunt.registerTask('dev', 'Dev Mode; watch files and restart server on changes',
['concat', 'copy:dev', 'emberBuild', 'express:dev', 'watch']);
['concat:dev', 'copy:dev', 'emberBuildDev', 'express:dev', 'watch']);
// ### Release
// Run `grunt release` to create a Ghost release zip file.
@ -797,7 +869,8 @@ var path = require('path'),
' - 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',
['shell:bower', 'update_submodules', 'concat', 'uglify', 'clean:release', 'copy:release', 'compress:release']);
['shell:bower', 'update_submodules', 'concat:prod', 'copy:prod', 'emberBuildProd', 'uglify',
'clean:release', 'copy:release', 'compress:release']);
};
// Export the configuration

View file

@ -1,3 +0,0 @@
var AppAdapter = DS.FixtureAdapter.extend({});
export default AppAdapter;

View file

@ -1,25 +1,18 @@
import Resolver from 'ember/resolver';
import initFixtures from 'ghost/fixtures/init';
import loadInitializers from 'ember/load-initializers';
import 'ghost/utils/link-view';
import 'ghost/utils/text-field';
import configureApp from 'ghost/config';
Ember.MODEL_FACTORY_INJECTIONS = true;
var App = Ember.Application.extend({
/**
* These are debugging flags, they are useful during development
*/
LOG_ACTIVE_GENERATION: true,
LOG_MODULE_RESOLVER: true,
LOG_TRANSITIONS: true,
LOG_TRANSITIONS_INTERNAL: true,
LOG_VIEW_LOOKUPS: true,
modulePrefix: 'ghost',
Resolver: Resolver['default']
});
initFixtures();
// Runtime configuration of Ember.Application
configureApp(App);
loadInitializers(App, 'ghost');

15
core/client/config-dev.js Normal file
View file

@ -0,0 +1,15 @@
function configureApp(App) {
if (!App instanceof Ember.Application) {
return;
}
App.reopen({
LOG_ACTIVE_GENERATION: true,
LOG_MODULE_RESOLVER: true,
LOG_TRANSITIONS: true,
LOG_TRANSITIONS_INTERNAL: true,
LOG_VIEW_LOOKUPS: true
});
}
export default configureApp;

View file

@ -0,0 +1,7 @@
function configureApp(App) {
if (!App instanceof Ember.Application) {
return;
}
}
export default configureApp;

View file

@ -1,68 +0,0 @@
var apps = [
{
'id': 1,
'name': 'testApp',
'package': {
'name': 'testApp',
'version': '2.0.1',
'description': 'An example application showing how to filter jquery from ghost foot',
'author': 'Ghost Foundation',
'homepage': 'http://ghost.org',
'repository': {
'type': 'git',
'url': 'git://github.com/TryGhost/Example-Apps'
},
'licenses': [
{
'type': 'MIT',
'url': 'https://raw.github.com/TryGhost/Example-Apps/master/LICENSE'
}
],
'main': 'index.js',
'engines': {
'node': '0.10.*'
},
'engineStrict': true,
'dependencies': {
'ghost-app': '~0.0.2',
'lodash': '~2.4.1'
},
'devDependencies': {}
},
'active': true
},
{
'id': 2,
'name': 'testApp2',
'package': {
'name': 'testApp2',
'version': '0.1.1',
'description': 'An example application showing how to filter jquery from ghost foot',
'author': 'Ghost Foundation',
'homepage': 'http://ghost.org',
'repository': {
'type': 'git',
'url': 'git://github.com/TryGhost/Example-Apps'
},
'licenses': [
{
'type': 'MIT',
'url': 'https://raw.github.com/TryGhost/Example-Apps/master/LICENSE'
}
],
'main': 'index.js',
'engines': {
'node': '0.10.*'
},
'engineStrict': true,
'dependencies': {
'ghost-app': '~0.0.2',
'lodash': '~2.4.1'
},
'devDependencies': {}
},
'active': false
},
];
export default apps;

View file

@ -1,68 +0,0 @@
import postFixtures from 'ghost/fixtures/posts';
import userFixtures from 'ghost/fixtures/users';
import settingsFixtures from 'ghost/fixtures/settings';
import appFixtures from 'ghost/fixtures/apps';
var response = function (responseBody, status) {
status = status || 200;
var textStatus = (status === 200) ? 'success' : 'error';
return {
response: responseBody,
jqXHR: { status: status },
textStatus: textStatus
};
};
var user = function (status) {
return response(userFixtures.findBy('id', 1), status);
};
var post = function (id, status) {
return response(postFixtures.findBy('id', id), status);
};
var posts = function (status) {
return response({
'posts': postFixtures,
'page': 1,
'limit': 15,
'pages': 1,
'total': 2
}, status);
};
var settings = function (status) {
return response(settingsFixtures, status);
};
var apps = function (status) {
return response(appFixtures, status);
};
var defineFixtures = function (status) {
ic.ajax.defineFixture('/ghost/api/v0.1/posts', posts(status));
ic.ajax.defineFixture('/ghost/api/v0.1/posts/1', post(1, status));
ic.ajax.defineFixture('/ghost/api/v0.1/posts/2', post(2, status));
ic.ajax.defineFixture('/ghost/api/v0.1/posts/3', post(3, status));
ic.ajax.defineFixture('/ghost/api/v0.1/posts/4', post(4, status));
ic.ajax.defineFixture('/ghost/api/v0.1/slugs/post/test%20title/', response('generated-slug', status));
ic.ajax.defineFixture('/ghost/api/v0.1/users/me/', user(status));
ic.ajax.defineFixture('/ghost/changepw/', response({
msg: 'Password changed successfully'
}));
ic.ajax.defineFixture('/ghost/api/v0.1/forgotten/', response({
redirect: '/ghost/signin/'
}));
ic.ajax.defineFixture('/ghost/api/v0.1/reset/', response({
msg: 'Password changed successfully'
}));
ic.ajax.defineFixture('/ghost/api/v0.1/settings/?type=blog,theme,app', settings(status));
ic.ajax.defineFixture('/ghost/api/v0.1/apps', apps(status));
ic.ajax.defineFixture('/ghost/api/v0.1/apps/1', response({
response: 'success'
}));
};
export default defineFixtures;

View file

@ -1,132 +0,0 @@
Fixtures for the Ghost blogging platform, intended to be generated with http://www.json-generator.com/
The generator's index() starts a 0, remove first 'post' to match expected data format.
{
posts: [
'{{repeat(31)}}',
{
id: '{{index()}}',
uuid: '{{guid()}}',
status: '{{random("published", "draft")}}',
title: '{{lorem( integer(1, 10), "words")}}',
slug: function(tag, index){
return this.title.replace(/ /g, '-');
},
markdown: '{{lorem( integer(1, 10), "paragraphs")}}',
html: function(tag, index){
return "<p>" + this.markdown + "</p>";
},
image: null,
featured: '{{integer(0, 1)}}',
page: '{{integer(0, 1)}}',
language: "en_US",
meta_title: null,
meta_description: null,
author: {
id: '{{integer(1, 10)}}',
uuid: '{{guid()}}',
name: '{{firstName()}} {{surname()}}',
slug: function(tag, index){
return this.name.replace(/ /g, '-').toLocaleLowerCase();
},
email: '{{email()}}',
image: undefined,
cover: undefined,
bio: '{{lorem(5, 50, "words")}}',
website: "",
location: '{{lorem( integer(1, 3), "words")}}',
accessibility: undefined,
status: "active",
language: "en_US",
meta_title: undefined,
meta_description: undefined,
created_at: '{{date(new Date(2012, 0, 1), new Date(), "YYYY-MM-ddThh:mm:ss.ff Z")}}',
updated_at: '{{date(new Date(2012, 0, 1), new Date(), "YYYY-MM-ddThh:mm:ss.ff Z")}}'
},
created_at: '{{date(new Date(2012, 0, 1), new Date(), "YYYY-MM-ddThh:mm:ss.ff Z")}}',
created_by: {
id: '{{integer(1, 10)}}',
uuid: '{{guid()}}',
name: '{{firstName()}} {{surname()}}',
slug: function(tag, index){
return this.name.replace(/ /g, '-').toLocaleLowerCase();
},
email: '{{email()}}',
image: undefined,
cover: undefined,
bio: '{{lorem(5, 50, "words")}}',
website: "",
location: '{{lorem( integer(1, 3), "words")}}',
accessibility: undefined,
status: "active",
language: "en_US",
meta_title: undefined,
meta_description: undefined,
created_at: '{{date(new Date(2012, 0, 1), new Date(), "YYYY-MM-ddThh:mm:ss.ff Z")}}',
updated_at: '{{date(new Date(2012, 0, 1), new Date(), "YYYY-MM-ddThh:mm:ss.ff Z")}}'
},
updated_at: '{{date(new Date(2012, 0, 1), new Date(), "YYYY-MM-ddThh:mm:ss.ff Z")}}',
updated_by: {
id: '{{integer(1, 10)}}',
uuid: '{{guid()}}',
name: '{{firstName()}} {{surname()}}',
slug: function(tag, index){
return this.name.replace(/ /g, '-').toLocaleLowerCase();
},
email: '{{email()}}',
image: undefined,
cover: undefined,
bio: '{{lorem(5, 50, "words")}}',
website: "",
location: '{{lorem( integer(1, 3), "words")}}',
accessibility: undefined,
status: "active",
language: "en_US",
meta_title: undefined,
meta_description: undefined,
created_at: '{{date(new Date(2012, 0, 1), new Date(), "YYYY-MM-ddThh:mm:ss.ff Z")}}',
updated_at: '{{date(new Date(2012, 0, 1), new Date(), "YYYY-MM-ddThh:mm:ss.ff Z")}}'
},
published_at: '{{date(new Date(2012, 0, 1), new Date(), "YYYY-MM-ddThh:mm:ss.ff Z")}}',
published_by: {
id: '{{integer(1, 10)}}',
uuid: '{{guid()}}',
name: '{{firstName()}} {{surname()}}',
slug: function(tag, index){
return this.name.replace(/ /g, '-').toLocaleLowerCase();
},
email: '{{email()}}',
image: undefined,
cover: undefined,
bio: '{{lorem(5, 50, "words")}}',
website: "",
location: '{{lorem( integer(1, 3), "words")}}',
accessibility: undefined,
status: "active",
language: "en_US",
meta_title: undefined,
meta_description: undefined,
created_at: '{{date(new Date(2012, 0, 1), new Date(), "YYYY-MM-ddThh:mm:ss.ff Z")}}',
updated_at: '{{date(new Date(2012, 0, 1), new Date(), "YYYY-MM-ddThh:mm:ss.ff Z")}}'
},
tags: [
'{{repeat(0, 10)}}',
{
id: '{{integer(1, 100)}}',
uuid: '{{guid()}}',
name: '{{lorem( integer(1, 3), "words")}}',
slug: function(tag, index){
return this.name.replace(/ /g, '-').toLocaleLowerCase();
},
description: null,
parent_id: null,
meta_title: null,
meta_description: null,
created_at: '{{date(new Date(2012, 0, 1), new Date(), "YYYY-MM-ddThh:mm:ss.ff Z")}}',
created_by: '{{integer(0, 10)}}',
updated_at: '{{date(new Date(2012, 0, 1), new Date(), "YYYY-MM-ddThh:mm:ss.ff Z")}}',
updated_by: '{{integer(0, 10)}}'
}
]
}]
}

File diff suppressed because it is too large Load diff

View file

@ -1,26 +0,0 @@
/* jshint ignore:start */
var settings = {
"title": "Ghost",
"description": "Just a blogging platform.",
"email": "ghost@tryghost.org",
"logo": "http://media-cache-ec0.pinimg.com/236x/be/35/06/be35065e6f9a613d4a7661a6f45d0831.jpg",
"cover": "http://i906.photobucket.com/albums/ac267/df853/bring_me_a_shrubbery_cat.jpg",
"defaultLang": "en_US",
"postsPerPage": "6",
"forceI18n": "true",
"permalinks": "/:slug/",
"activeTheme": "casper",
"activeApps": "[]",
"installedApps": "[]",
"availableThemes": [
{
"name": "casper",
"package": false,
"active": true
}
],
"availableApps": []
};
export default settings;
/* jshint ignore:end */

View file

@ -1,25 +0,0 @@
/* jshint ignore:start */
var users = [
{
"id": 1,
"uuid": "ba9c67e4-8046-4b8c-9349-0eed3cca7529",
"name": "some-user",
"slug": "some-user",
"email": "some@email.com",
"image": undefined,
"cover": undefined,
"bio": "Example bio",
"website": "",
"location": "Imaginationland",
"accessibility": undefined,
"status": "active",
"language": "en_US",
"meta_title": undefined,
"meta_description": undefined,
"created_at": "2014-02-15T20:02:25.000Z",
"updated_at": "2014-03-11T14:06:43.000Z"
}
];
export default users;
/* jshint ignore:end */

View file

@ -1,13 +0,0 @@
import appFixtures from 'ghost/fixtures/apps';
var App = DS.Model.extend({
name: DS.attr('string'),
package: DS.attr(),
active: DS.attr('boolean')
});
App.reopenClass({
FIXTURES: appFixtures
});
export default App;

View file

@ -22,19 +22,13 @@ var downsize = require('downsize'),
scriptFiles = {
production: [
'ghost.min.js'
'vendor.min.js',
'ghost.min.js',
],
development: [
'vendor.js',
'helpers.js',
'templates.js',
'models.js',
'views.js'
],
ember: [
'vendor-ember.js',
'templates-ember.js',
'ghost-dev-ember.js'
'vendor-dev.js',
'templates-dev.js',
'ghost-dev.js'
]
};
@ -42,7 +36,6 @@ if (!isProduction) {
hbs.handlebars.logger.level = 0;
}
// [ description]
//
// @param {Object} context date object
@ -370,7 +363,7 @@ coreHelpers.apps = function (context, options) {
};
coreHelpers.ghost_script_tags = function () {
var scriptList = scriptFiles.ember;
var scriptList = isProduction ? scriptFiles.production : scriptFiles.development;
scriptList = _.map(scriptList, function (fileName) {
return scriptTemplate({

View file

@ -78,7 +78,8 @@ function builtFilesExist() {
var deferreds = [],
location = config().paths.builtScriptPath,
fileNames = helpers.scriptFiles.ember;
fileNames = process.env.NODE_ENV === 'production' ?
helpers.scriptFiles.production : helpers.scriptFiles.development;
function checkExist(fileName) {
var deferred = when.defer(),

View file

@ -407,7 +407,7 @@ describe('Frontend Routing', function () {
});
it('should retrieve built assets', function (done) {
request.get('/ghost/scripts/vendor-ember.js')
request.get('/ghost/scripts/vendor-dev.js')
.expect('Cache-Control', cacheRules.year)
.expect(200)
.end(doEnd(done));

View file

@ -1382,9 +1382,9 @@ describe('Core Helpers', function () {
rendered = helpers.ghost_script_tags();
should.exist(rendered);
String(rendered).should.equal(
'<script src="/ghost/scripts/vendor-ember.js?v=abc"></script>' +
'<script src="/ghost/scripts/templates-ember.js?v=abc"></script>' +
'<script src="/ghost/scripts/ghost-dev-ember.js?v=abc"></script>'
'<script src="/ghost/scripts/vendor-dev.js?v=abc"></script>' +
'<script src="/ghost/scripts/templates-dev.js?v=abc"></script>' +
'<script src="/ghost/scripts/ghost-dev.js?v=abc"></script>'
);
overrideConfig({
@ -1395,9 +1395,9 @@ describe('Core Helpers', function () {
rendered = helpers.ghost_script_tags();
should.exist(rendered);
String(rendered).should.equal(
'<script src="/blog/ghost/scripts/vendor-ember.js?v=abc"></script>' +
'<script src="/blog/ghost/scripts/templates-ember.js?v=abc"></script>' +
'<script src="/blog/ghost/scripts/ghost-dev-ember.js?v=abc"></script>'
'<script src="/blog/ghost/scripts/vendor-dev.js?v=abc"></script>' +
'<script src="/blog/ghost/scripts/templates-dev.js?v=abc"></script>' +
'<script src="/blog/ghost/scripts/ghost-dev.js?v=abc"></script>'
);
});
@ -1408,9 +1408,8 @@ describe('Core Helpers', function () {
rendered = helpers.ghost_script_tags();
should.exist(rendered);
String(rendered).should.equal(
'<script src="/ghost/scripts/vendor-ember.js?v=abc"></script>' +
'<script src="/ghost/scripts/templates-ember.js?v=abc"></script>' +
'<script src="/ghost/scripts/ghost-dev-ember.js?v=abc"></script>'
'<script src="/ghost/scripts/vendor.min.js?v=abc"></script>' +
'<script src="/ghost/scripts/ghost.min.js?v=abc"></script>'
);
overrideConfig({
@ -1421,9 +1420,8 @@ describe('Core Helpers', function () {
rendered = helpers.ghost_script_tags();
should.exist(rendered);
String(rendered).should.equal(
'<script src="/blog/ghost/scripts/vendor-ember.js?v=abc"></script>' +
'<script src="/blog/ghost/scripts/templates-ember.js?v=abc"></script>' +
'<script src="/blog/ghost/scripts/ghost-dev-ember.js?v=abc"></script>'
'<script src="/blog/ghost/scripts/vendor.min.js?v=abc"></script>' +
'<script src="/blog/ghost/scripts/ghost.min.js?v=abc"></script>'
);
});
});

View file

@ -80,7 +80,7 @@
"grunt-contrib-concat": "~0.4.0",
"grunt-contrib-copy": "~0.4.1",
"grunt-contrib-jshint": "~0.8.0",
"grunt-contrib-uglify": "~0.2.5",
"grunt-contrib-uglify": "~0.5.0",
"grunt-contrib-watch": "~0.5.3",
"grunt-docker": "~0.0.8",
"grunt-ember-templates": "~0.4.18",