Adds slashes to urls

ref issue #448

- adds slashes to urls, templates and tests

TODO

Add function to add slash to urls automatically
This commit is contained in:
cobbspur 2013-09-15 12:13:06 +01:00 committed by Hannah Wolfe
parent 09ca5e6298
commit 713e4c0d5c
19 changed files with 50 additions and 52 deletions

View File

@ -50,7 +50,7 @@
nextPage: 0,
prevPage: 0,
url: Ghost.settings.apiRoot + '/posts',
url: Ghost.settings.apiRoot + '/posts/',
model: Ghost.Models.Post,
parse: function (resp) {

View File

@ -3,7 +3,7 @@
"use strict";
//id:0 is used to issue PUT requests
Ghost.Models.Settings = Backbone.Model.extend({
url: Ghost.settings.apiRoot + '/settings?type=blog,theme',
url: Ghost.settings.apiRoot + '/settings/?type=blog,theme',
id: "0"
});

View File

@ -3,6 +3,6 @@
"use strict";
Ghost.Collections.Tags = Backbone.Collection.extend({
url: Ghost.settings.apiRoot + '/tags'
url: Ghost.settings.apiRoot + '/tags/'
});
}());

View File

@ -0,0 +1,9 @@
/*global window, document, Ghost, $, _, Backbone */
(function () {
"use strict";
Ghost.Models.Themes = Backbone.Model.extend({
url: Ghost.settings.apiRoot + '/themes'
});
}());

View File

@ -3,11 +3,11 @@
"use strict";
Ghost.Models.User = Backbone.Model.extend({
url: Ghost.settings.apiRoot + '/users/me'
url: Ghost.settings.apiRoot + '/users/me/'
});
// Ghost.Collections.Users = Backbone.Collection.extend({
// url: Ghost.settings.apiRoot + '/users'
// url: Ghost.settings.apiRoot + '/users/'
// });
}());

View File

@ -36,7 +36,7 @@
});
Ghost.Collections.Widgets = Backbone.Collection.extend({
// url: Ghost.settings.apiRoot + '/widgets', // What will this be?
// url: Ghost.settings.apiRoot + '/widgets/', // What will this be?
model: Ghost.Models.Widget
});

View File

@ -7,10 +7,8 @@
routes: {
'' : 'blog',
'content/' : 'blog',
'settings/' : 'settings',
'settings(/:pane)' : 'settings',
'editor/' : 'editor',
'editor(/:id)' : 'editor',
'settings(/:pane)/' : 'settings',
'editor(/:id)/' : 'editor',
'debug/' : 'debug',
'register/' : 'register',
'signup/' : 'signup',
@ -40,7 +38,7 @@
settings: function (pane) {
if (!pane) {
// Redirect to settings/general if no pane supplied
this.navigate('/settings/general', {
this.navigate('/settings/general/', {
trigger: true,
replace: true
});

View File

@ -26,7 +26,7 @@
{{#if logo}}
<a class="js-modal-logo" href="#"><img id="blog-logo" src="{{logo}}" alt="logo"></a>
{{else}}
<a class="button-add js-modal-logo" href="#">Upload Image</a>
<a class="button-add js-modal-logo" >Upload Image</a>
{{/if}}
<p>Display a sexy logo for your publication</p>
</div>
@ -36,7 +36,7 @@
{{#if cover}}
<a class="js-modal-cover" href="#"><img id="blog-cover" src="{{cover}}" alt="cover photo"></a>
{{else}}
<a class="button-add js-modal-cover" href="#">Upload Image</a>
<a class="button-add js-modal-cover">Upload Image</a>
{{/if}}
<p>Display a cover image on your site</p>
</div>

View File

@ -186,7 +186,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/editor/' + this.model.get('id') + '/';
},
templateName: "preview",

View File

@ -94,7 +94,7 @@
});
this.listenTo(this.model, 'change:status', this.render);
this.model.on('change:id', function (m) {
Backbone.history.navigate('/editor/' + m.id);
Backbone.history.navigate('/editor/' + m.id + '/');
});
},
@ -660,4 +660,4 @@
});
};
}());
}());

View File

@ -59,7 +59,7 @@
var self = this,
model;
Ghost.router.navigate('/settings/' + id);
Ghost.router.navigate('/settings/' + id + '/');
Ghost.trigger('urlchange');
if (this.pane && id === this.pane.el.id) {
return;

View File

@ -301,15 +301,15 @@ when.all([ghost.init(), helpers.loadCoreHelpers(ghost)]).then(function () {
server.put('/api/v0.1/posts/:id', authAPI, disableCachedResult, api.requestHandler(api.posts.edit));
server.del('/api/v0.1/posts/:id', authAPI, disableCachedResult, api.requestHandler(api.posts.destroy));
// #### Settings
server.get('/api/v0.1/settings', authAPI, disableCachedResult, api.requestHandler(api.settings.browse));
server.get('/api/v0.1/settings/:key', authAPI, disableCachedResult, api.requestHandler(api.settings.read));
server.put('/api/v0.1/settings', authAPI, disableCachedResult, api.requestHandler(api.settings.edit));
server.get('/api/v0.1/settings/', authAPI, disableCachedResult, api.requestHandler(api.settings.browse));
server.get('/api/v0.1/settings/:key/', authAPI, disableCachedResult, api.requestHandler(api.settings.read));
server.put('/api/v0.1/settings/', authAPI, disableCachedResult, api.requestHandler(api.settings.edit));
// #### Users
server.get('/api/v0.1/users', authAPI, disableCachedResult, api.requestHandler(api.users.browse));
server.get('/api/v0.1/users/:id', authAPI, disableCachedResult, api.requestHandler(api.users.read));
server.put('/api/v0.1/users/:id', authAPI, disableCachedResult, api.requestHandler(api.users.edit));
server.get('/api/v0.1/users/', authAPI, disableCachedResult, api.requestHandler(api.users.browse));
server.get('/api/v0.1/users/:id/', authAPI, disableCachedResult, api.requestHandler(api.users.read));
server.put('/api/v0.1/users/:id/', authAPI, disableCachedResult, api.requestHandler(api.users.edit));
// #### Tags
server.get('/api/v0.1/tags', authAPI, disableCachedResult, api.requestHandler(api.tags.all));
server.get('/api/v0.1/tags/', authAPI, disableCachedResult, api.requestHandler(api.tags.all));
// #### Notifications
server.del('/api/v0.1/notifications/:id', authAPI, disableCachedResult, api.requestHandler(api.notifications.destroy));
server.post('/api/v0.1/notifications/', authAPI, disableCachedResult, api.requestHandler(api.notifications.add));
@ -331,9 +331,9 @@ when.all([ghost.init(), helpers.loadCoreHelpers(ghost)]).then(function () {
server.post('/ghost/signin/', admin.auth);
server.post('/ghost/signup/', admin.doRegister);
server.post('/ghost/changepw/', auth, admin.changepw);
server.get('/ghost/editor/:id', auth, admin.editor);
server.get('/ghost/editor', auth, admin.editor);
server.get('/ghost/content', auth, admin.content);
server.get('/ghost/editor(/:id)/', auth, admin.editor);
server.get('/ghost/editor/', auth, admin.editor);
server.get('/ghost/content/', auth, admin.content);
server.get('/ghost/settings*', auth, admin.settings);
server.get('/ghost/debug/', auth, admin.debug.index);
server.get('/ghost/debug/db/export/', auth, admin.debug['export']);

View File

@ -76,7 +76,7 @@ coreHelpers = function (ghost) {
}
if (models.isPost(this)) {
output += "/" + this.slug;
output += "/" + this.slug + '/';
}
return output;

View File

@ -5,7 +5,7 @@
<section class="content-filter">
<span>All Posts</span>
</section>
<a href="/ghost/editor" class="button button-add"><span class="hidden">New Post</span></a>
<a href="/ghost/editor/" class="button button-add"><span class="hidden">New Post</span></a>
</header>
<section class="content-list-content">
<ol></ol>

View File

@ -13,7 +13,7 @@
<span class="name">{{#if currentUser.name}}{{currentUser.name}}{{else}}Ghost{{/if}} v{{version}}</span>
</a>
<ul class="overlay">
<li class="usermenu-profile"><a href="/ghost/settings/user">Your Profile</a></li>
<li class="usermenu-profile"><a href="/ghost/settings/user/">Your Profile</a></li>
<li class="divider"></li>
<li class="usermenu-help"><a href="http://forum.tryghost.org">Help / Support</a></li>
<li class="divider"></li>

View File

@ -1,21 +1,15 @@
/*globals casper, __utils__, url, testPost */
casper.test.begin("Ghost editor is correct", 10, function suite(test) {
casper.test.begin("Ghost editor is correct", 9, function suite(test) {
test.filename = "editor_test.png";
casper.start(url + "ghost/editor", function testTitleAndUrl() {
casper.start(url + "ghost/editor/", function testTitleAndUrl() {
test.assertTitle("", "Ghost admin has no title");
test.assertUrlMatch(/ghost\/editor$/, "Ghost doesn't require login this time");
test.assertUrlMatch(/ghost\/editor\/$/, "Ghost doesn't require login this time");
test.assertExists(".entry-markdown", "Ghost editor is present");
test.assertExists(".entry-preview", "Ghost preview is present");
}).viewport(1280, 1024);
function handleResource(resource) {
if (resource.url === url + 'api/v0.1/posts') {
casper.removeListener('resource.received', handleResource);
casper.test.assertEquals(resource.status, 200, "Received correct response");
}
}
// test saving with no data
casper.thenClick('.js-publish-button');
@ -35,8 +29,6 @@ casper.test.begin("Ghost editor is correct", 10, function suite(test) {
// We must wait after sending keys to CodeMirror
casper.wait(1000, function doneWait() {
this.echo("I've waited for 1 seconds.");
// bind to resource events so we can get the API response
casper.on('resource.received', handleResource);
});
casper.thenClick('.js-publish-button');
@ -54,7 +46,6 @@ casper.test.begin("Ghost editor is correct", 10, function suite(test) {
});
casper.run(function () {
casper.removeListener('resource.received', handleResource);
test.done();
});
});
@ -63,7 +54,7 @@ casper.test.begin("Ghost editor is correct", 10, function suite(test) {
casper.test.begin("Haunted markdown in editor works", 3, function suite(test) {
test.filename = "markdown_test.png";
casper.start(url + "ghost/editor", function testTitleAndUrl() {
casper.start(url + "ghost/editor/", function testTitleAndUrl() {
test.assertTitle("", "Ghost admin has no title");
}).viewport(1280, 1024);
@ -94,7 +85,7 @@ casper.test.begin("Haunted markdown in editor works", 3, function suite(test) {
casper.test.begin("Word count and plurality", 4, function suite(test) {
test.filename = "editor_plurality_test.png";
casper.start(url + "ghost/editor", function testTitleAndUrl() {
casper.start(url + "ghost/editor/", function testTitleAndUrl() {
test.assertTitle("", "Ghost admin has no title");
}).viewport(1280, 1024);

View File

@ -3,9 +3,9 @@
casper.test.begin("Settings screen is correct", 15, function suite(test) {
test.filename = "settings_test.png";
casper.start(url + "ghost/settings", function testTitleAndUrl() {
casper.start(url + "ghost/settings/", function testTitleAndUrl() {
test.assertTitle("", "Ghost admin has no title");
test.assertUrlMatch(/ghost\/settings\/general$/, "Ghost doesn't require login this time");
test.assertUrlMatch(/ghost\/settings\/general\/$/, "Ghost doesn't require login this time");
}).viewport(1280, 1024);
casper.then(function testViews() {
@ -117,9 +117,9 @@ casper.test.begin("User settings screen validates email", 6, function suite(test
test.filename = "user_settings_test.png";
casper.start(url + "ghost/settings/user", function testTitleAndUrl() {
casper.start(url + "ghost/settings/user/", function testTitleAndUrl() {
test.assertTitle("", "Ghost admin has no title");
test.assertUrlMatch(/ghost\/settings\/user$/, "Ghost doesn't require login this time");
test.assertUrlMatch(/ghost\/settings\/user\/$/, "Ghost doesn't require login this time");
}).viewport(1280, 1024);
casper.then(function setEmailToInvalid() {

View File

@ -6,8 +6,8 @@
casper.test.begin("Ghost edit draft flow works correctly", 7, function suite(test) {
test.filename = "flow_test.png";
casper.start(url + "ghost/editor", function then() {
test.assertUrlMatch(/ghost\/editor$/, "Ghost doesn't require login this time");
casper.start(url + "ghost/editor/", function then() {
test.assertUrlMatch(/ghost\/editor\/$/, "Ghost doesn't require login this time");
}).viewport(1280, 1024);
// First, create a new draft post

View File

@ -215,7 +215,7 @@ describe('Core Helpers', function () {
it('should return a the slug with a prefix slash if the context is a post', function () {
var rendered = handlebars.helpers.url.call({html: 'content', markdown: "ff", title: "title", slug: "slug"});
should.exist(rendered);
rendered.should.equal('/slug');
rendered.should.equal('/slug/');
});
it('should output an absolute URL if the option is present', function () {
@ -229,7 +229,7 @@ describe('Core Helpers', function () {
);
should.exist(rendered);
rendered.should.equal('http://testurl.com/slug');
rendered.should.equal('http://testurl.com/slug/');
configStub.restore();
});