I’ve been writing some things that could fit into a blog post(node-tooling or some of the resources of fullstack) but I never dedicated time and effort to set up one. This is the story on how I modified a blog framework to suit my needs.

Narrowing down the contenders

For a few weeks now I’ve been working on a side project with lots of data visualizations and thought it would be a good idea not only to write about it but also include some interactions in the blog post itself. I wanted the flexibility to modify the HTML and JavaScript (more like inserting chunks of HTML and JavaScript in this case) as I see fit.
These requirements ended up ruling out Wordpress, Jekyll, Ghost and Medium as viable options. It’s not that Wordpress would restrict you to modify its source but PHP nor their huge codebase are things I’m familiar with. This is were Hexo comes in and, if necessary, I would find easier to look at JavaScript code.

Another very important feature for me was the ability to publish posts in both English and Spanish.

Always go back to the source

After installing and creating a new blog with hexo-cli you’ll end up with a directory structure like the following:

1
2
3
4
5
6
7
8
9
.
├── _config.yml
├── db.json
├── node_modules
├── package.json
├── public
├── scaffolds
├── source
└── themes

“source” is the directory where you’ll save your pages (“About”, “Tags”, etc) and blog posts.

I created two new blog posts (you can create one by executing hexo new post yourPostTitle) with the same identifier (see Front-matter) to know that, although they are in different languages, they represent the same post. That, of course, would mean for Hexo to display two different posts in your “Home” or “Archives” pages.

My first attempt in solving the duplicates issue was modifying the template’s logic. After playing around with Jade Pug and solving the problem partially I realized it would not integrate well with other components like pagination and more importantly it would be a theme-based solution, if for some reason I decide to switch to other theme I would have to solve the problem once again.

Hexo has a collection (stored in a json file generated from your “source/_posts” directory) for posts and that collection is injected to all the front-end sections like “Home”, “Archive”, “About”, etc. Adding a query parameter to the query that returns all the posts wouldn’t solve the problem since it will erase all generated files from the translated posts.

I had to follow what exactly hexo generate was doing to get more insight on how to do it: there’s a folder containing a file for each component it will generate (“assets”, “page” and “post”). Looking inside the “post.js” file you’ll found that it’s iterating over the posts collection and setting up the content that it’s not specific to the post itself, like the post.prev and post.next references. Since it doesn’t interacts directly with the rest of the components it could be a good place to add the changes that I want.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var translatedPosts = locals.translatedPosts.toArray();
var translatedResults = translatedPosts.map(function(translatedPost){
var originalPost = results.find(function(r){
return r.data.postId === translatedPost.postId;
});

translatedPost.prev = originalPost.data.prev;
translatedPost.next = originalPost.data.next;
return {
path: translatedPost.path,
layout: ['post', 'page', 'index'],
data: translatedPost
};
});

The previous code will iterate over a list of translated posts and mock the post.prev and post.next references to be the same ones that the original post had.

Now all we need to do is set the translatedPosts variable with our collection of translated posts:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
locals.set('translatedPosts', function() {
var query = {};

if (!self.config.future) {
query.date = {$lte: Date.now()};
}

if (!self._showDrafts()) {
query.published = true;
}
query.translated = true;

return db.model('Post').find(query);
});

I added the previous code after the set up of the posts reference in line 122 of index.js.

I’ve also modified the template for posts to show links to other translations if present, but that will remain to be theme-specific.

Conclusions

I found that Hexo is flexible in a lot of ways and that the code is both readable and structured.

You can view all the changes mentioned here at my fork of Hexo. If you have questions or suggestions on other ways to do these changes please write to me on the comments.