Preface

Goal: Using data feature.

There is no such things as database connection in static site generator.

However, we can use static data, to fulfill simple requirement.

Table of Content

  • Preface: Table of Content

  • 1: Outside Link: Friends

  • 2: Outside Link: Backlinks

  • 3: Local Link: Related Post

  • What is Next ?

Source Code

You can download the source code of this article here.

Extract and run on CLI:

$ npm install

Static Data

Suppossed, we want to show all blog site, at widget in the sidebar. Instead of manually coding the html, we can prepare the data.

# Isle of friends

- title: "BanditHijo (R)-Chive"
  url: http://bandithijo.com/

- title: "Sira Argia (Aflasio)"
  url: https://aflasio.netlify.com/

- title: "Rania Amina"
  url: https://raniaamina.github.io/

This might looks stupid, because we can directly write the result in html. But in the next example, we can show you how data can be dynamic.

Later we can access this simple data using site.data.friends.

Layout: EJS Page

Do not forget to change the page.ejs, to examine only friends widget:

  <aside class="sidebar column is-one-thirds is-paddingless">
    <%- partial('widget/friends') %>
  </aside>

Javascript: Widget: EJS Friends

This require javascript, to shuffle the array.

/**
 * Randomly shuffle an array
 * https://stackoverflow.com/a/2450976/1293256
 * @param  {Array} array The array to shuffle
 * @return {String}      The first item in the shuffled array
 */
var shuffle = function (array) {

  var currentIndex = array.length;
  var temporaryValue, randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {
    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    // And swap it with the current element.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
};
  • .

Layout: Widget: EJS Friends

Now consider pour the javascript to HTML template in EJS artefact below:

<%
  ...
%>

<section class="panel is-light">
  <div class="panel-header">
    <p>Isle of Friends</p>
    <span class="fa fa-child"></span>
  </div>
  <div class="panel-body has-background-white">
    <ul class="panel-list">
      <% friends = shuffle(site.data.friends).slice(-5) %>
      <% friends.forEach(function(friend){ %>
      <li><a href="<%= friend.url %>"
         ><%= friend.title %></a></li>
      <% }) %>
    </ul>
  </div>
</section>

The Loop

I also shuffle the result so for each page they shown randomly.

      <% friends = shuffle(site.data.friends).slice(-5) %>
      <% friends.forEach(function(friend){ %>
        ...
      <% }) %>

Render: Browser

Now you can see the result in the browser.

Hexo: Widget Friends


Why not go further? Instead of just showing your friends domain name, you can put backlink of external blogs in your widget. As long as the backlink is relevant to your content, you are safe.

Static Data

Yes, we can automate this!

Suppossed, you have different blog, and you to show articles of your other blog, at widget in the sidebar. Instead of manually coding the html, we can prepare the data.

or other blog as well

# Helper for related links

- id: 19061119
  title: "Conky with Lua Scripting"
  url: /desktop/2019/06/11/modularized-conky.html

- id: 19040245
  title: "GhostBSD - Ports"
  url: /system/2019/04/02/ghostbsd-ports.html

- id: 19033045
  title: "GhostBSD - Migration from Linux"
  url: /system/2019/03/30/ghostbsd-migration.html

All you need are only title and url. And you can ignore id. The id serve different purpose for other widget, as we will discuss later.

We will also discuss how to achieve this external data in other article.

This require the same javascript, in friends.ejs as above, to shuffle the array.

Now consider pour the javascript to HTML template in EJS artefact below:

<%
  ...
%>

<section class="panel is-light">
  <div class="panel-header">
    <p>Linux/BSD Customization</p>
    <span class="fa fa-child"></span>
  </div>
  <div class="panel-body has-background-white">
    <ul class="panel-list">
      <% friends = shuffle(site.data.archives_github).slice(-5) %>
      <% friends.forEach(function(friend){ %>
      <li><a href="http://epsi-rns.github.io<%= friend.url %>"
         ><%= friend.title %></a></li>
      <% }) %>
    </ul>
  </div>
</section>

We can access this simple data, using site.data.archives_github.

We can als setup other blog as well as shown in widget below:

Render: Browser

Now you can see the result in the browser.

Hexo: Widget Archives epsi-rns.github.io

And with the same method we can setup widget for other blog as well.

Hexo: Widget Archives epsi-rns.gitlab.io


3: Local Link: Related Post

Remember our last archives page ? Yeah, the yaml data one. We can use it here.

Static Data

The data look like here below:

# Helper for related links
# Archives by Date

...

- id: 15010108
  title: "Dead Poet Society"
  url: 2015/01/01/quotes/dead-poets-society/

- id: 15100308
  title: "Every Day"
  url: 2015/10/03/quotes/every-day/

...

Hexo: Data Archives

Data Generator

So what is it, the id field ? Well, our data related posts , need a simple data id. But since we do not have RDBMS, we can emulate the id. We are going to use the id from the date field in frontmatter.

Let me remind you how the data generated from script below:

# Helper for related links
# <%= page.title %>

<% site.posts.each(function(post){ %>
- id: <%= date(post.date, "YYMMDDmm") %>
  title: "<%= post.title %>"
  url: <%= post.path %>
<% }) %>

The format “YYMMDDmm”, means [year-month-date-minute]. It is rarely, that I blog with the same minute in the same day. This way, the id would be unique.

Manual Download

The data/archives.yml itself is generated. We have already discuss custom content type in previous chapter. But there are more steps to do:

I know, it seems tricky, but it works well so far.

Layout: EJS Post

Do not forget to change the post.ejs, to examine only related-posts widget:

  <aside class="sidebar column is-one-thirds is-paddingless">
    <%- partial('widget/related-posts') %>
  </aside>

Now that we already have the id, it is time to use the data.

<% if (page.related_link_ids) { %>
<section class="panel is-light">
  <div class="panel-header">
    <p>Related Posts</p>
    <span class="fa fa-link"></span>
  </div>
  <div class="panel-body has-background-white">
    <ul class="panel-list">
      <% page.related_link_ids.forEach(function (id){ %>
      <li>
        <% site.data.archives.forEach(function(archive){ %>

          <% if (archive.id == id) { %>
          <a href="<%= url_for(archive.url) %>"><%= archive.title %></a>
          <% } %>

        <% }) %>
      </li>
      <% }) %>
    </ul>
  </div>
</section>
<% } %>

Data Source: Two Options

Code above is using YAML as data source:

Alternatively, you can use JSON as data source:

And change the data source in the code as below:

...
        <% site.data.archives_local.forEach(function(archive){ %>
          ...
        <% }) %>
...

Content: Example

If we want to use it, related_link_ids in frontmatter. Consider this example.

---
title     : Susan Wong - I Wish You Love
date      : 2015/05/15 07:35:05
tags      : [pop, 70s]
category  : [lyric]

related_link_ids: 
  - 15051515  # The Way We Were
---

I wish you bluebirds in the spring  
To give your heart a song to sing

<!-- more --> 

I wish you health  
And more than wealth  
I wish you love

Hexo: Content with Data

Server Output: Browser

Now you can see the result in the browser.

Hexo: Widget Related Posts


What is Next ?

Consider continue reading [ Hexo - Pagination - Introduction ]. There are, some interesting topic about Pagination in Hexo.

Thank you for reading.