Skip to content

Commit

Permalink
Merge branch '1.0.0-rc4'
Browse files Browse the repository at this point in the history
  • Loading branch information
jsantell committed Feb 2, 2014
2 parents 4dbb60a + 310d0aa commit cfc456e
Show file tree
Hide file tree
Showing 15 changed files with 231 additions and 72 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Change Log

## v1.0.0-rc4
* :warning: The `routes` configuration option during instantiation will no longer create routes that are not explicitly defined, unless using defaults, issue #71
* Leaving `routes` as empty will continue to use the default routing.
* Setting `routes` to `null` will not set any routes.
* Setting `routes` to an object will only define routes specified in that object. Therefore, using an empty object will not set any routes.
* :warning: Post slugs are now created from the `title` attribute instead of the file name. Slugs can also be customized by adding a `slug` attribute in a post, issue #64, issue #69
* Bake version of `marked` and `json-front-matter` to be consistent with previous versions -- can include newer versions with custom templating.
* Handles errors more gracefully when posts cannot compile with their template, issue #61

## v1.0.0-rc3

* Added async templating processing, issue #50
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ View the source for [jsantell.com](https://github.com/jsantell/jsantell.com) to

## New Release

**v1.0.0-rc3**
**v1.0.0-rc4**
A giant refactor has occurred -- all tests are passing, and be sure to test when upgrading to this release candidate. Some features may be missing or not working as intended. If you notice any issues, please file a bug.

Some features have been removed and changed, so please note the changes in the change log -- your site may need to be slightly changed to accomodate the 1.x.x releases from previous versions.

[**Changes in v1.0.0-rc3**](https://github.com/jsantell/poet/blob/master/CHANGELOG.md)
[**Changes in v1.0.0-rc4**](https://github.com/jsantell/poet/blob/master/CHANGELOG.md)

## Documentation

Expand Down
16 changes: 11 additions & 5 deletions lib/poet/methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ function init (poet, callback) {
// If no template found, ignore (swap file, etc.)
if (!template) return coll;

// If template function accepts more than one argument, then handle 2nd
// argument as asynchronous node-style callback function
// If template function accepts more than one argument, then handle 2nd
// argument as asynchronous node-style callback function
if (template.length > 1) {
template = function(template, string) {
var result = defer();
Expand All @@ -67,14 +67,20 @@ function init (poet, callback) {
// Do the templating and adding to poet instance
// here for access to the file name
var post = utils.createPost(file, options).then(function (post) {
return all([template(post.content), template(post.preview)]).then(function (contents) {
return all([template(post.content), template(post.preview)]).then(function (contents) {
post.content = contents[0];
post.preview = contents[1] + options.readMoreLink(post);
poet.posts[post.slug] = post;
});
}, function (reason) {
console.error('Unable to parse file ' + file + ': ' + reason);
post = undefined;
});

coll.push(post);
if (post) {
coll.push(post);
}

return coll;
}, []);

Expand All @@ -94,7 +100,7 @@ function init (poet, callback) {
exports.init = init;

/**
* Clears the `poet` instance's 'cache' object -- useful when modifying
* Clears the `poet` instance's 'cache' object -- useful when modifying
* posts dynamically
*
* @params {Object} poet
Expand Down
3 changes: 3 additions & 0 deletions lib/poet/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ function bindRoutes (poet) {
var app = poet.app;
var routes = poet.options.routes;

// If no routes specified, abort
if (!routes) return;

Object.keys(routes).map(function (route) {
var type = utils.getRouteType(route);
if (!type) return;
Expand Down
44 changes: 17 additions & 27 deletions lib/poet/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,7 @@ var
*/

function createOptions (options) {
var defaults = createDefaults();
options = options || {};
// Merge options with defaults
var union = Object.keys(defaults).reduce(function (coll, prop) {
// If property is an object, make a clone of it
if (typeof defaults[prop] === 'object') {
coll[prop] = _.extend({}, options[prop] || defaults[prop]);
} else {
coll[prop] = options[prop] != null ? options[prop] : defaults[prop];
}
return coll;
}, {});

for (key in options) {
if (!union.hasOwnProperty(key)) {
union[key] = options[key];
}
}

return union;
return _.extend({}, createDefaults(), options || {});
}
exports.createOptions = createOptions;

Expand All @@ -49,6 +30,9 @@ exports.createOptions = createOptions;
*/

function createURL (route, value) {
if (!route) {
return '';
}
return encodeURI(route.match(/[^\:]*/)[0] + value);
}
exports.createURL = createURL;
Expand Down Expand Up @@ -155,6 +139,13 @@ function getTemplate (templates, fileName) {
}
exports.getTemplate = getTemplate;

function convertStringToSlug(str){
return str
.toLowerCase()
.replace(/[^\w- ]+/g,'')
.replace(/ +/g,'-');
}

/**
* Accepts a name of a file and an options hash and returns an object
* representing a post object
Expand All @@ -171,14 +162,12 @@ function createPost (filePath, options) {
var parsed = (options.metaFormat === 'yaml' ? yamlFm : jsonFm)(data);
var body = parsed.body;
var post = parsed.attributes;
var shortName = fileName.replace(/\.[^\.]*$/, '');

// If no date defined, create one for current date
post.date = new Date(post.date);

post.content = body;
post.slug = shortName;
post.url = createURL(getRoute(options.routes, 'post'), shortName);
// url slug for post
post.slug = convertStringToSlug(post.slug || post.title);
post.url = createURL(getRoute(options.routes, 'post'), post.slug);
post.preview = getPreview(post, body, options);
return post;
});
Expand Down Expand Up @@ -257,14 +246,15 @@ exports.getRouteType = getRouteType;

/**
* Takes a hash of `routes`, and a `type` (ex: 'post'), and returns
* the corresponding route regex as a string
* the corresponding route regex as a string. If no route found, returns `null`.
*
* @params {Object} routes
* @params {String} type
* @returns {String}
* @returns {String|Null}
*/

function getRoute (routes, type) {
if (!routes) return null;
return Object.keys(routes).reduce(function (match, route) {
return getRouteType(route) === type ? route : match;
}, null);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "poet",
"description": "quick and easy blog module, using markdown, jade, whatever",
"version": "1.0.0-rc3",
"version": "1.0.0-rc4",
"main": "lib/poet",
"dependencies": {
"marked": "0.2.8",
Expand Down
4 changes: 2 additions & 2 deletions test/helpers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ describe('helpers.getPostCount()', function () {
describe('helpers.getPost(title)', function () {
it('should return the correct post associated with `title`', function (done) {
setup(function (poet) {
var post = poet.helpers.getPost('jadeTemplate');
expect(post.slug).to.be.equal('jadeTemplate');
var post = poet.helpers.getPost('jade-test');
expect(post.slug).to.be.equal('jade-test');
expect(post.title).to.be.equal('Jade Test');
done();
}, done);
Expand Down
2 changes: 1 addition & 1 deletion test/helpers/routeInfo.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
exports.getCallback = function ( app, path ) {
var get_length = app.routes.get.length;
var get_length = app.routes.get ? app.routes.get.length : 0;

for (var i = 0; i < get_length; i++) {
if (app.routes.get[i].path == path) {
Expand Down
2 changes: 1 addition & 1 deletion test/init.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('Init', function () {
});

poet.init().then(function () {
expect(poet.posts['test1']).to.be.ok;
expect(poet.posts['test-post-one']).to.be.ok;
expect(poet.helpers.getPosts().length).to.be.ok;
done();
}).then(null, done);
Expand Down
12 changes: 6 additions & 6 deletions test/options.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ var
expect = chai.expect;

var
readMoreLink = '<a href="/post/test2">Test Post Two</a>';
readMoreLink = '<a href="/post/test-post-two">Test Post Two</a>';

describe('Options', function () {
describe('readMoreLink', function () {
Expand All @@ -21,16 +21,16 @@ describe('Options', function () {
});

poet.init().then(function () {
poet.posts['test2'].preview.should.equal(
poet.posts['test-post-two'].preview.should.equal(
'<p><em>some content</em></p>' + "\n" + readMoreLink);
done();
}).then(null, done);
});
});

describe('readMoreTag', function () {
var customPreview = '<p><em>Lorem ipsum</em></p>\n<p><a href="/post/readMore" title="Read more of Read More Test">read more</a></p>',
defaultPreview = '<p><em>Lorem ipsum</em>\n!!!more!!!\n<em>more ipsum</em></p>\n<p><a href="/post/readMore" title="Read more of Read More Test">read more</a></p>';
var customPreview = '<p><em>Lorem ipsum</em></p>\n<p><a href="/post/read-more-test" title="Read more of Read More Test">read more</a></p>',
defaultPreview = '<p><em>Lorem ipsum</em>\n!!!more!!!\n<em>more ipsum</em></p>\n<p><a href="/post/read-more-test" title="Read more of Read More Test">read more</a></p>';

it('should by default use <!--more-->', function (done) {
var
Expand All @@ -40,7 +40,7 @@ describe('Options', function () {
});

poet.init().then(function () {
poet.posts['readMore'].preview.should.equal(defaultPreview);
poet.posts['read-more-test'].preview.should.equal(defaultPreview);
done();
}).then(null, done);
});
Expand All @@ -53,7 +53,7 @@ describe('Options', function () {
readMoreTag: '!!!more!!!'
});
poet.init().then(function () {
poet.posts['readMore'].preview.should.equal(customPreview);
poet.posts['read-more-test'].preview.should.equal(customPreview);
done();
}).then(null, done);
});
Expand Down
97 changes: 81 additions & 16 deletions test/posts.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ var
var
postPreview = '<p><em>Lorem ipsum</em> dolor sit amet, consectetur adipisicing elit.</p>',
postBody = '<p><em>Lorem ipsum</em> dolor sit amet, consectetur adipisicing elit.</p>\n<h1>Header 1</h1>\n',
readMoreAnchorp1 = '<p><a href="/post/test1" title="Read more of Test Post One">read more</a></p>',
readMoreAnchorp2 = '<p><a href="/post/test2" title="Read more of Test Post Two">read more</a></p>';
readMoreAnchorp3 = '<p><a href="/post/test3" title="Read more of Test Post Three">read more</a></p>';
readMoreAnchorp1 = '<p><a href="/post/test-post-one" title="Read more of Test Post One">read more</a></p>',
readMoreAnchorp2 = '<p><a href="/post/test-post-two" title="Read more of Test Post Two">read more</a></p>';
readMoreAnchorp3 = '<p><a href="/post/test-post-three" title="Read more of Test Post Three">read more</a></p>';

describe('Posts', function () {
describe('Posts with JSON front-matter', function () {
Expand All @@ -25,17 +25,18 @@ describe('Posts', function () {
poet.init().then(function () {
var posts = poet.helpers.getPosts();
posts.should.have.length(6);
poet.posts['test1'].slug.should.equal('test1');
poet.posts['test1'].tags.should.have.length(2);
poet.posts['test1'].tags.should.include('a');
poet.posts['test1'].tags.should.include('b');
poet.posts['test1'].category.should.equal('testing');
poet.posts['test1'].url.should.equal('/post/test1');
poet.posts['test1'].arbitrary.should.equal('arbitrary content');
var post = poet.posts['test-post-one'];
post.slug.should.equal('test-post-one');
post.tags.should.have.length(2);
post.tags.should.include('a');
post.tags.should.include('b');
post.category.should.equal('testing');
post.url.should.equal('/post/test-post-one');
post.arbitrary.should.equal('arbitrary content');

// Also tests HTML rendering
poet.posts['test1'].preview.should.equal(postPreview + "\n" + readMoreAnchorp1 );
poet.posts['test1'].content.should.equal(postBody);
post.preview.should.equal(postPreview + "\n" + readMoreAnchorp1 );
post.content.should.equal(postBody);

// All posts should be in order
posts[5].title.should.equals('Test Post Four - A Draft');
Expand Down Expand Up @@ -84,12 +85,12 @@ describe('Posts', function () {
var posts = poet.helpers.getPosts();
posts.should.have.length(4);
posts[2].title.should.equal('Test Post One');
posts[2].slug.should.equal('test1');
posts[2].slug.should.equal('test-post-one');
posts[2].tags.should.have.length(2);
posts[2].tags.should.include('a');
posts[2].tags.should.include('b');
posts[2].category.should.equal('testing');
posts[2].url.should.equal('/post/test1');
posts[2].url.should.equal('/post/test-post-one');
posts[2].arbitrary.should.equal('arbitrary content');

// Also tests HTML rendering
Expand Down Expand Up @@ -136,7 +137,9 @@ describe('Posts', function () {
poet.init().then(function () {
var posts = poet.helpers.getPosts();
posts.should.have.length(2);
poet.helpers.getPost('deep').should.be.ok;
poet.helpers.getPost('test-post-one').should.be.ok;
poet.helpers.getPost('deep-post').should.be.ok;
poet.helpers.getPost('deep-post').url.should.be.equal('/post/deep-post');
done();
}).then(null, done);
});
Expand All @@ -147,7 +150,7 @@ describe('Posts', function () {
var
app = express(),
poet = Poet(app, {
posts: './test/test.posts'
posts: './test/test-posts/period.path'
});

poet.init().then(function () {
Expand All @@ -157,4 +160,66 @@ describe('Posts', function () {
}).then(null, done);
});
});

describe('Post Attributes', function () {
it('slug attribute overrides default slug and changes URL', function (done) {
var
app = express(),
poet = Poet(app, {
posts: './test/test-posts/slug'
});

poet.init().then(function () {
var posts = poet.helpers.getPosts();
posts[0].slug.should.be.equal('custom-slug');
posts[0].url.should.be.equal('/post/custom-slug');
done();
}).then(null, done);
});

it('post.url and readMore links updates when using custom routes in constructor', function (done) {
var
app = express(),
poet = Poet(app, {
posts: './test/test-posts/slug',
routes: {
'post-oh-yeah/:post': 'post',
'posts-oh-yeah/:posts': 'posts',
'tags-oh-yeah/:tag': 'tag',
'cats-oh-yeah/:category': 'category'
}
});

poet.init().then(function () {
var posts = poet.helpers.getPosts();
posts[0].slug.should.be.equal('custom-slug');
posts[0].url.should.be.equal('post-oh-yeah/custom-slug');
posts[0].preview.should.contain('href="post-oh-yeah/custom-slug"');
done();
}).then(null, done);
});

it('post.url and readMore links updates when using addRoute', function (done) {
var
app = express(),
poet = Poet(app, {
posts: './test/test-posts/slug',
routes: {}
});

var handler = function () {}
poet.addRoute('/myposts/:post', handler);
poet.addRoute('/pagesss/:page', handler);
poet.addRoute('/mytags/:tag', handler);
poet.addRoute('/mycats/:category', handler);

poet.init().then(function () {
var posts = poet.helpers.getPosts();
posts[0].slug.should.be.equal('custom-slug');
posts[0].url.should.be.equal('/myposts/custom-slug');
posts[0].preview.should.contain('href="/myposts/custom-slug"');
done();
}).then(null, done);
});
});
});
Loading

0 comments on commit cfc456e

Please sign in to comment.