diff --git a/core/client/assets/lib/uploader.js b/core/client/assets/lib/uploader.js
index 29b1aac556..039511a441 100644
--- a/core/client/assets/lib/uploader.js
+++ b/core/client/assets/lib/uploader.js
@@ -47,7 +47,7 @@
.attr({'src': '', "width": 'auto', "height": 'auto'});
$progress.animate({"opacity": 0}, 250, function () {
- $dropzone.find('span.media').after('');
+ $dropzone.find('span.media').after('');
if (!settings.editor) {$progress.find('.fileupload-loading').css({"top": "56px"}); }
});
$dropzone.trigger("uploadsuccess", [result]);
@@ -62,7 +62,7 @@
var self = this;
$dropzone.find('.js-fileupload').fileupload().fileupload("option", {
- url: '/ghost/upload/',
+ url: Ghost.paths.ghostRoot + '/ghost/upload/',
headers: {
'X-CSRF-Token': $("meta[name='csrf-param']").attr('content')
},
diff --git a/core/client/init.js b/core/client/init.js
index e0e987831c..e11a2c80a4 100644
--- a/core/client/init.js
+++ b/core/client/init.js
@@ -2,6 +2,16 @@
(function () {
'use strict';
+ function ghostPaths() {
+ var path = window.location.pathname,
+ root = path.substr(0, path.search('/ghost/'));
+
+ return {
+ ghostRoot: root,
+ apiRoot: root + '/ghost/api/v0.1'
+ };
+ }
+
var Ghost = {
Layout : {},
Views : {},
@@ -9,9 +19,7 @@
Models : {},
Validate : new Validator(),
- settings: {
- apiRoot: '/ghost/api/v0.1'
- },
+ paths: ghostPaths(),
// This is a helper object to denote legacy things in the
// middle of being transitioned.
@@ -46,7 +54,7 @@
Backbone.history.start({
pushState: true,
hashChange: false,
- root: '/ghost'
+ root: Ghost.paths.ghostRoot + '/ghost'
});
};
diff --git a/core/client/models/post.js b/core/client/models/post.js
index 666ba51872..ea367b7ee8 100644
--- a/core/client/models/post.js
+++ b/core/client/models/post.js
@@ -50,7 +50,7 @@
nextPage: 0,
prevPage: 0,
- url: Ghost.settings.apiRoot + '/posts/',
+ url: Ghost.paths.apiRoot + '/posts/',
model: Ghost.Models.Post,
parse: function (resp) {
diff --git a/core/client/models/settings.js b/core/client/models/settings.js
index 82f1dc1212..2048fbee51 100644
--- a/core/client/models/settings.js
+++ b/core/client/models/settings.js
@@ -3,7 +3,7 @@
'use strict';
//id:0 is used to issue PUT requests
Ghost.Models.Settings = Ghost.ProgressModel.extend({
- url: Ghost.settings.apiRoot + '/settings/?type=blog,theme',
+ url: Ghost.paths.apiRoot + '/settings/?type=blog,theme',
id: '0',
parse: function (resp) {
resp.permalinks = resp.permalinks === "/:slug/" ? "" : "1";
diff --git a/core/client/models/tag.js b/core/client/models/tag.js
index d903c67075..4661480578 100644
--- a/core/client/models/tag.js
+++ b/core/client/models/tag.js
@@ -3,6 +3,6 @@
'use strict';
Ghost.Collections.Tags = Ghost.ProgressCollection.extend({
- url: Ghost.settings.apiRoot + '/tags/'
+ url: Ghost.paths.apiRoot + '/tags/'
});
}());
diff --git a/core/client/models/themes.js b/core/client/models/themes.js
index 5e82d77201..cf76c1d806 100644
--- a/core/client/models/themes.js
+++ b/core/client/models/themes.js
@@ -3,7 +3,7 @@
'use strict';
Ghost.Models.Themes = Backbone.Model.extend({
- url: Ghost.settings.apiRoot + '/themes'
+ url: Ghost.paths.apiRoot + '/themes'
});
-}());
\ No newline at end of file
+}());
diff --git a/core/client/models/user.js b/core/client/models/user.js
index d90a91a49f..47aa87ca5b 100644
--- a/core/client/models/user.js
+++ b/core/client/models/user.js
@@ -3,11 +3,11 @@
'use strict';
Ghost.Models.User = Ghost.ProgressModel.extend({
- url: Ghost.settings.apiRoot + '/users/me/'
+ url: Ghost.paths.apiRoot + '/users/me/'
});
// Ghost.Collections.Users = Backbone.Collection.extend({
-// url: Ghost.settings.apiRoot + '/users/'
+// url: Ghost.paths.apiRoot + '/users/'
// });
}());
diff --git a/core/client/models/widget.js b/core/client/models/widget.js
index 65d5a53101..f26cf79c93 100644
--- a/core/client/models/widget.js
+++ b/core/client/models/widget.js
@@ -36,8 +36,8 @@
});
Ghost.Collections.Widgets = Ghost.ProgressCollection.extend({
- // url: Ghost.settings.apiRoot + '/widgets/', // What will this be?
+ // url: Ghost.paths.apiRoot + '/widgets/', // What will this be?
model: Ghost.Models.Widget
});
-}());
\ No newline at end of file
+}());
diff --git a/core/client/router.js b/core/client/router.js
index e0cadb1d03..b58c2454a8 100644
--- a/core/client/router.js
+++ b/core/client/router.js
@@ -60,7 +60,7 @@
editor: function (id) {
var post = new Ghost.Models.Post();
- post.urlRoot = Ghost.settings.apiRoot + '/posts';
+ post.urlRoot = Ghost.paths.apiRoot + '/posts';
if (id) {
post.id = id;
post.fetch({ data: {status: 'all'}}).then(function () {
diff --git a/core/client/views/base.js b/core/client/views/base.js
index 8b9d439dfb..aa93b16087 100644
--- a/core/client/views/base.js
+++ b/core/client/views/base.js
@@ -205,7 +205,7 @@
headers: {
'X-CSRF-Token': $("meta[name='csrf-param']").attr('content')
},
- url: Ghost.settings.apiRoot + '/notifications/' + $(self).find('.close').data('id')
+ url: Ghost.paths.apiRoot + '/notifications/' + $(self).find('.close').data('id')
}).done(function (result) {
/*jslint unparam:true*/
bbSelf.$el.slideUp(250, function () {
@@ -239,7 +239,7 @@
headers: {
'X-CSRF-Token': $("meta[name='csrf-param']").attr('content')
},
- url: Ghost.settings.apiRoot + '/notifications/' + $(self).data('id')
+ url: Ghost.paths.apiRoot + '/notifications/' + $(self).data('id')
}).done(function (result) {
/*jslint unparam:true*/
var height = bbSelf.$('.js-notification').outerHeight(true),
diff --git a/core/client/views/blog.js b/core/client/views/blog.js
index aeecbca789..ea2764e6db 100644
--- a/core/client/views/blog.js
+++ b/core/client/views/blog.js
@@ -214,7 +214,7 @@
e.preventDefault();
// for now this will disable "open in new tab", but when we have a Router implemented
// it can go back to being a normal link to '#/ghost/editor/X'
- window.location = '/ghost/editor/' + this.model.get('id') + '/';
+ window.location = Ghost.paths.ghostRoot + '/ghost/editor/' + this.model.get('id') + '/';
},
toggleFeatured: function (e) {
diff --git a/core/client/views/login.js b/core/client/views/login.js
index 7da7b78a30..ac8eba668d 100644
--- a/core/client/views/login.js
+++ b/core/client/views/login.js
@@ -35,7 +35,7 @@
Ghost.Validate.handleErrors();
} else {
$.ajax({
- url: '/ghost/signin/',
+ url: Ghost.paths.ghostRoot + '/ghost/signin/',
type: 'POST',
headers: {
'X-CSRF-Token': $("meta[name='csrf-param']").attr('content')
@@ -100,7 +100,7 @@
Ghost.Validate.handleErrors();
} else {
$.ajax({
- url: '/ghost/signup/',
+ url: Ghost.paths.ghostRoot + '/ghost/signup/',
type: 'POST',
headers: {
'X-CSRF-Token': $("meta[name='csrf-param']").attr('content')
@@ -157,7 +157,7 @@
Ghost.Validate.handleErrors();
} else {
$.ajax({
- url: '/ghost/forgotten/',
+ url: Ghost.paths.ghostRoot + '/ghost/forgotten/',
type: 'POST',
headers: {
'X-CSRF-Token': $("meta[name='csrf-param']").attr('content')
@@ -224,7 +224,7 @@
this.$('input, button').prop('disabled', true);
$.ajax({
- url: '/ghost/reset/' + this.token + '/',
+ url: Ghost.paths.ghostRoot + '/ghost/reset/' + this.token + '/',
type: 'POST',
headers: {
'X-CSRF-Token': $("meta[name='csrf-param']").attr('content')
diff --git a/core/client/views/post-settings.js b/core/client/views/post-settings.js
index 2ae9425863..2b0cd3b5a1 100644
--- a/core/client/views/post-settings.js
+++ b/core/client/views/post-settings.js
@@ -211,7 +211,7 @@
}).then(function () {
// Redirect to content screen if deleting post from editor.
if (window.location.pathname.indexOf('editor') > -1) {
- window.location = '/ghost/content/';
+ window.location = Ghost.paths.ghostRoot + '/ghost/content/';
}
Ghost.notifications.addItem({
type: 'success',
diff --git a/core/server/helpers/index.js b/core/server/helpers/index.js
index 8417d5c6d2..df69f5fddb 100644
--- a/core/server/helpers/index.js
+++ b/core/server/helpers/index.js
@@ -113,6 +113,35 @@ coreHelpers.url = function (options) {
return output;
};
+// ### Asset helper
+//
+// *Usage example:*
+// `{{asset src="css/screen.css"}}`
+// `{{asset src="css/screen.css" ghost="true"}}`
+//
+// Returns the path to the specified asset. The ghost
+// flag outputs the asset path for the Ghost admin
+coreHelpers.asset = function (context, options) {
+ var output = '',
+ subDir = coreHelpers.ghost.blogGlobals().path,
+ isAdmin = options && options.hash && options.hash.ghost;
+
+ if (subDir === '/') {
+ output += '/';
+ } else {
+ output += subDir + '/';
+ }
+
+ if (isAdmin) {
+ output += 'ghost/';
+ } else {
+ output += 'assets/';
+ }
+
+ output += context;
+ return new hbs.handlebars.SafeString(output);
+};
+
// ### Author Helper
//
// *Usage example:*
@@ -540,47 +569,49 @@ registerHelpers = function (ghost, config) {
// And expose config
coreHelpers.config = config;
- ghost.registerThemeHelper('date', coreHelpers.date);
-
- ghost.registerThemeHelper('encode', coreHelpers.encode);
-
- ghost.registerThemeHelper('pageUrl', coreHelpers.pageUrl);
-
- ghost.registerThemeHelper('url', coreHelpers.url);
+ ghost.registerThemeHelper('asset', coreHelpers.asset);
ghost.registerThemeHelper('author', coreHelpers.author);
- ghost.registerThemeHelper('tags', coreHelpers.tags);
-
ghost.registerThemeHelper('content', coreHelpers.content);
+ ghost.registerThemeHelper('date', coreHelpers.date);
+
+ ghost.registerThemeHelper('e', coreHelpers.e);
+
+ ghost.registerThemeHelper('encode', coreHelpers.encode);
+
ghost.registerThemeHelper('excerpt', coreHelpers.excerpt);
ghost.registerThemeHelper('fileStorage', coreHelpers.fileStorage);
- ghost.registerThemeHelper('ghostScriptTags', coreHelpers.ghostScriptTags);
-
- ghost.registerThemeHelper('e', coreHelpers.e);
-
- ghost.registerThemeHelper('json', coreHelpers.json);
-
ghost.registerThemeHelper('foreach', coreHelpers.foreach);
- ghost.registerThemeHelper('helperMissing', coreHelpers.helperMissing);
+ ghost.registerThemeHelper('ghostScriptTags', coreHelpers.ghostScriptTags);
ghost.registerThemeHelper('has_tag', coreHelpers.has_tag);
+ ghost.registerThemeHelper('helperMissing', coreHelpers.helperMissing);
+
+ ghost.registerThemeHelper('json', coreHelpers.json);
+
+ ghost.registerThemeHelper('pageUrl', coreHelpers.pageUrl);
+
+ ghost.registerThemeHelper('tags', coreHelpers.tags);
+
+ ghost.registerThemeHelper('url', coreHelpers.url);
+
ghost.registerAsyncThemeHelper('body_class', coreHelpers.body_class);
- ghost.registerAsyncThemeHelper('post_class', coreHelpers.post_class);
-
- ghost.registerAsyncThemeHelper('meta_title', coreHelpers.meta_title);
-
- ghost.registerAsyncThemeHelper('meta_description', coreHelpers.meta_description);
+ ghost.registerAsyncThemeHelper('ghost_foot', coreHelpers.ghost_foot);
ghost.registerAsyncThemeHelper('ghost_head', coreHelpers.ghost_head);
- ghost.registerAsyncThemeHelper('ghost_foot', coreHelpers.ghost_foot);
+ ghost.registerAsyncThemeHelper('meta_description', coreHelpers.meta_description);
+
+ ghost.registerAsyncThemeHelper('meta_title', coreHelpers.meta_title);
+
+ ghost.registerAsyncThemeHelper('post_class', coreHelpers.post_class);
paginationHelper = ghost.loadTemplate('pagination').then(function (templateFn) {
coreHelpers.paginationTemplate = templateFn;
diff --git a/core/server/middleware/index.js b/core/server/middleware/index.js
index 3f492db957..127c423a98 100644
--- a/core/server/middleware/index.js
+++ b/core/server/middleware/index.js
@@ -187,7 +187,7 @@ module.exports = function (server) {
server.use(express.session({
store: new BSStore(ghost.dataProvider),
secret: ghost.dbHash,
- cookie: { path: '/ghost', maxAge: 12 * 60 * 60 * 1000 }
+ cookie: { path: root + '/ghost', maxAge: 12 * 60 * 60 * 1000 }
}));
//enable express csrf protection
diff --git a/core/server/views/content.hbs b/core/server/views/content.hbs
index c8a14927bf..0969717ba8 100644
--- a/core/server/views/content.hbs
+++ b/core/server/views/content.hbs
@@ -5,7 +5,7 @@
@@ -14,4 +14,4 @@