Hexo: How to make a home page out of multiple markdown files?

Created on 24 Jan 2017  ·  13Comments  ·  Source: hexojs/hexo

I've been playing with hexo for a few days now but so far I have not been able to figure out how I can make one single home page(public/index.html) that would consist of 3 columns, each displaying the contents of a different markdown file.

This is the result I'm trying to get: https://gsokolowski.pl/ (personal site)

The thing is in hexo it seems I can have only one source/index.md file being generated directly into one public/index.html file. How can I change that to make one public/index.html file out of source/index_col{1,2,3}.md files, each in different column div?

Maybe I'm reading the documentation wrong but I can't seem to find a way to do this.

question

All 13 comments

Hello,
To have a custom HTML index page, you would need to create an index.ejs file and place it within your layouts folder, then you can add whatever custom HTML you want. Have a look at: https://hexo.io/docs/templates.html#Layouts for more information on template hierarchy.

If you want to have say a custom about me page, then in your about.md file you can addlayout: about to your front-matter and then create a about.ejs and place it within your layouts folder and you can then style that as you want.

Since you are new to Hexo, I would recommend looking at this minimal theme: https://github.com/nadymain/hexo-theme-nadymain/tree/master/layout there you can see how the index.ejs file works together with the other templates.

Any questions let me know.

I'm sorry but I just don't get it, hexo looks like a very cool tool but it's documentation is extremely terse, short, and does not go in depth into anything.

You are telling me that I can generate about.html out of source/about.md through a template in layouts/about.ejs. But I don't understand a few things:

  • How can I split the contents of source/about.md in layouts/about.ejs in order to generate 3 separate columns(divs) with 3 articles out of it in about.html, and not just one article? I know the contents attribute will contain the whole markdown document, but that's not what I want.
  • If that's not doable how can I make about.html out of layouts/about.ejs by combining source/about_col1.md, source/about_col2.md, and source/about_col3.md, into separate parts of the page? I might add that those files are NOT posts in the blog, they are simple contents of different divs in my about page.
  • How can I reference a specific markdown file in source directory and it's contents(rendered into html) from an EJS template?

Thanks! Looks promising, I'll try it out today.

@PonderingGrower Did you got it working? There is this one year old Hexo plugin @NoahDragon mentioned but if I got it correctly it is for included Markdown files within another, so to say 'root' Markdown file.
Whereas I seek for the exact same solution as you, so rendering specific Markdown files within EJS templates.

Do you have a solution for our problem? :)

I'm testing it right now but it seems like hexo doesn't recognize the include_md command. I added it in scripts/index.js like this:

/* index.js */
var fs   = require('fs');
var path = require('path');
var util = require('util');
/* markdown converter I choose to use, you can use whatever fits your need */
var marked = require('marked');

/**
 * Include markdown tag
 * Syntax:
 *   {% include_md path/to/file %}
 */

var include_md = function(args, content) {
    var render = hexo.render;
    var sourceDir = hexo.source_dir;
    var arg = args.join(' ');
    var data = {};
    var filepath = path.join(sourceDir, arg);

    /* Exit if the source file doesn't exist */
    if (!fs.existsSync(filepath)) {
        /* return the path for debugging */
        return filepath;
    }

    data.content = fs.readFileSync(filepath, 'utf8');

    return marked(data.content)
};

/* register the "include_md" tag to hexo */
hexo.extend.tag.register('include_md', include_md);

But all I'm getting when I'm trying to use it in source/test.html which looks like this:

{{ include_md index.md }}

Is this:

Template render error: (unknown path) [Line 8, Column 13]
  expected variable end
    at Object.exports.prettifyError (/home/sochan/work/blog/node_modules/hexo/node_modules/nunjucks/src/lib.js:34:15)
    at Obj.extend.render (/home/sochan/work/blog/node_modules/hexo/node_modules/nunjucks/src/environment.js:469:27)
    at Obj.extend.renderString (/home/sochan/work/blog/node_modules/hexo/node_modules/nunjucks/src/environment.js:327:21)
    at /home/sochan/work/blog/node_modules/hexo/lib/extend/tag.js:66:9
    at Promise._execute (/home/sochan/work/blog/node_modules/hexo/node_modules/bluebird/js/release/debuggability.js:300:9)
    at Promise._resolveFromExecutor (/home/sochan/work/blog/node_modules/hexo/node_modules/bluebird/js/release/promise.js:481:18)
    at new Promise (/home/sochan/work/blog/node_modules/hexo/node_modules/bluebird/js/release/promise.js:77:14)
    at Tag.render (/home/sochan/work/blog/node_modules/hexo/lib/extend/tag.js:64:10)
    at Object.tagFilter [as onRenderEnd] (/home/sochan/work/blog/node_modules/hexo/lib/hexo/post.js:253:16)
    at /home/sochan/work/blog/node_modules/hexo/lib/hexo/render.js:65:19
    at tryCatcher (/home/sochan/work/blog/node_modules/hexo/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/home/sochan/work/blog/node_modules/hexo/node_modules/bluebird/js/release/promise.js:510:31)
    at Promise._settlePromise (/home/sochan/work/blog/node_modules/hexo/node_modules/bluebird/js/release/promise.js:567:18)
    at Promise._settlePromise0 (/home/sochan/work/blog/node_modules/hexo/node_modules/bluebird/js/release/promise.js:612:10)
    at Promise._settlePromises (/home/sochan/work/blog/node_modules/hexo/node_modules/bluebird/js/release/promise.js:691:18)
    at Async._drainQueue (/home/sochan/work/blog/node_modules/hexo/node_modules/bluebird/js/release/async.js:133:16)
    at Async._drainQueues (/home/sochan/work/blog/node_modules/hexo/node_modules/bluebird/js/release/async.js:143:10)
    at Immediate.Async.drainQueues [as _onImmediate] (/home/sochan/work/blog/node_modules/hexo/node_modules/bluebird/js/release/async.js:17:14)
    at processImmediate [as _immediateCallback] (timers.js:396:17)

I'm not really sure what I'm doing wrong.

I guess I'm stupid, I should have use {% include_md index.md %} format.

Though when I do that the page just shows [object Promise].

But am I correct that the original usage for this plugin is to include Markdown files within another Markdown file? Which is not what we seek for!

I'm starting to think that there is just no intended way in Hexo to use more than one Markdown file within the same page. Isn't it?!

Are you referring to this: https://www.npmjs.com/package/hexo-tag-markdown ?

because that looks like it's supposed to be for markdown in markdown.

Yes, exactly!
I searched more as well and it honestly seems that Hexo assumes that one uses exactly one Markdown file per page or post.

Yeah, which is a pretty silly assumption.

I mean, for just posting article, that makes sense, but I for example have a very specific layout of my home page that required assembling specific 3 markdown documents in specific html divs.

I think with this JS script/tag I should be able to do this, though I'm still kinda struggling with forcing a template to look like I want it to.

@PonderingGrower So I had some thoughts and found quite a good workaround solution.

So if you just put your different Markdown files for example in the directory source/_posts you can access the array of posts like so:
page.posts.data

By default, you can use 'lodash' within Hexo templates.
So I thought let's use it to easily _find() (Documentation) our wanted Markdown file and use its front-matter and content.
So for example like this:
<% _.find(page.posts.data, ['title', 'your chosen title here']).content %>
one can easily output the content of the Markdown file with the title field in the front-matter set like so:

--- 
title: your chosen title here
---

You could also use:

<% console.log(_.find(page.posts.data, ['title', 'your chosen title here']).content) %>

to find out the other properties.

That way I will now start to build my page with different <div> elements with different Markdown sources.
I will write a plugin for that exact purpose if other people run into the same problem!
Hope that will help you! If I can still help, let me know :)

@PonderingGrower
As promised, I created a plugin for doing what we tried to achieve.
You can find it here: https://github.com/loehnertz/hexo-custom-fields
Please let me know if you can think of any additional features or if you have any questions! :blush:

Was this page helpful?
0 / 5 - 0 ratings