Author: Bian Xi

Learning – Middleman – Static Site Generator

Learning - Middleman - Static Site Generator

Install

  • Install Ruby
ruby --version
  • Install middleman
gem install middleman
middleman version

Install on Mac

Install xcode on Mac

xcode-select --install

Fix version issue in Mac

If encounter error on Mac indicating version low, run following command to install ruby version manager

curl -L https://get.rvm.io | bash -s stable

Restart terminal and run following command

rvm install ruby-2.4.2
rvm --default use ruby-2.4.2
ruby -v

Creating a site

middleman init ga_site

Then a folder called ga_site is created.

Run

middleman server

Access website via http://localhost:4567

Folders

source
source/images
source/javascripts
source/layouts
source/layouts/layout.erb - default layout
source/stylesheets
source/index.html.erb - default home page
config.rb
Gemfile

Activate LiveReload

LiveReload is able to reload the pages when they changed.

In config.rb file, add following line.

...
page...
...

activate :livereload

In Gemfile, add following line

gem 'middleman-livereload'

In project file, run following command

bundle install middleman-livereload

Restart middleman server

middleman server

Create html file ga_site/source/a.html.erb or ga_site/source/dir1/b.html.erb, then can access file from browser.

Note: If use .html without .erb, then it will not use default template.

Create markdown file as ga_site/source/c.html.md.erb.

Front Matter

Front matter can use JSON or YAML

YAML

---
title: Middleman is Running
author: "Mike"
---

JSON

;;;
"title": "New Title"
;;;

Access front matter variable

<%= current_page.data.author %>

Layouts

All pages are using source/layouts/layout.erb to display erb files. So, can modify the layout.erb file to change layout.

Helper Methods

Helpers are small codes can be used in markdown file.

<%= link_to 'Giraffe Academy', 'http://giraffeacademy.com' %>

To include ga_site/sources/styllesheets/ga_style

<%= stylesheet_link_tag 'ga_style' %>

To include ga_site/sources/javascripts/ga_code.js

<%= javascript_include_tag 'ga_code' %>

To include ga_site/source/images/log.png

<%= image_tag 'logo.png' %>

Other helpers can be found in middlemanapp.com

Layout

Default layout

The file ga_site/source/layouts/layout.erb is for all pages.

Specific layout

Create another layout2.erb file, then can be used in other markdown file using front matter as below a.html.erb.

---
layout: layout2
---

This is a.html

Layout for one directory

If want to specify all files in one directory use specific layout, can configure in config.rb file as below.

page '/dir1/*', layout: 'layout2'

Wrap layout

For example, the layout2 needs to use default layout and wrap it around, can be defined in layout2.erb file

<% wrap_layout :layout do %>
  New Layout <br> <hr>
  <%= yield %>
  <br><hr>New Layout
<% end %>

Partial

  • Create a folder ga_site/source/partials/, this is not mandatory.

  • Create partial file called _header.erb file, the leading _ is mandatory.

<h1>This is the Title</h1>
<br><hr>

To include in layout.erb file,

<%= partial 'partials/header' %>

Note: the leading _ and the tailing .erb are not shown in this statement, middleman knows how to find the file.

Passing variable

In layout.erb file

<%= partial(:'partials/header', :locals => { :title => 'My Title', :color => "blue" })

In _header.erb file

<h1 style="color: <%= color %>"><%= title %></h1>
<br><hr>

Data Files

Create a data folder as ga_site/data, create data file can be YAML or JSON files. For example test.yml

dog: "Golden Retriever"
products:
  - Tooth Brush
  - Shampoo
  - Soap

In layout.erb or index.erb file

<%= data.test.dog %>

or

<% data.test.products.each do |f| %>
  <li><%= f %></li>
<% end %>

If Statement

<% if current_page.data.title == "A" and current_page.data.author %>
  This is the A file
<% elsif current_page.data.title == "B" %>
  This is the B file
<% else %>
  This is not A or B
<% end %>

Sitemap

In layout.erb file

<% sitemap.resources.each do |f| %>
  <% if f.content_type.include? "html" %>
    <% f.data.title %> <br>
    <% f.path %> <br>
    <% f.content_type %> <br>
    <li><a href="<%= f.path %>"><%= f.data.title %></a></li>
  <% end %>
<% end %>

or

<% current_resource.parent.data.title %>

<% current_resource.siblings.each do |f| %>
  <% f.data.title %> <br>
<% end %>

<% current_resource.children.each do |f| %>
  <% f.data.title %> <br>
<% end %>

Building a Blog

First install blog generator

gem install middleman-blog

Initialize blog site

middleman init myBlog --template=blog

Start middleman blog server

cd myBlog
middleman server

Any file wants to be blog needs to be named as YYYY-MM-DD-title.md or created by following command

middleman article MyNewArticle
middleman article MyNewArticle

Also can add tags in the article

tags: example

or

tags: [example, tag2]

To list down all articles

<% blog.articles[0...10].each do |article| %>

<% end %>

Project Templates

Go to https://directory.middlemanapp.com/#/templates/all to download middleman templates

Once select the good one, run command

middleman init -T <template> <folder_name>

For example

middle init -T dtcristo/middleman-cactus cactus

Pretty URLs

Normally, to remove the extension of file in URL, create a folder, move the file in the folder, and rename the file as index.html.erb.

This can be done using configuration in config.rb

activate :directory_indexes

Install Extensions

Download extension from https://directory.middlemanapp.com/#/extensions/all website.

First, update Gemfile, add gem

gem 'middleman-minify-html'

The add configure in config.rb file

activate :minify_html

Then install gem

bundle install

Building Site

Run following command

middleman build

Then the website will be built in build directory.

References

Middleman - Static Site Generator | Tutorial

Learning – Gatsby – Static Site Generator

Learning - Gatsby - Static Site Generator

Installation

  • Install NodeJS
node --version
npm --version
  • Install gatsby
npm install --global gatsby-cli
gatsby --version

Create site

gatsby new ga_site https://github.com/gatsbyjs/gatsby-starter-hello-world

A new folder called ga_site is created.

Run

npm run develop

The site will be run on http://localhost:8000

Folders

node_modules - Used by NodeJS.
public - the site to be published
src - pages
src/pages/index.js - start up page
package.json - define NodeJS packages

Adding Content

In index.js, there are ReactJS scripts.

import React from "react"

export default() =>
  <div style={{color: 'tomato', backgroundColor: 'blue'}} >
    <h1>Hello world!</h1>
    <p>This is a paragraph</p>
  </div>

Note: When writing contents in ReactJS, only one HTML element can be used in one statement.

Linking Pages

Add Link in index.js

import React from "react"
import Link from "gatsby-link"

export default() =>
  <div style={{color: 'tomato', backgroundColor: 'blue'}} >
    <h1>Hello world!</h1>
    <p>This is a paragraph</p>
    <Link to="/page-2/">Page 2</Link>
  </div>

Create a file src/pages/page-2.js

import React from "react"
import Link from "gatsby-link"

export default() =>
  <div style={{color: 'tomato', backgroundColor: 'blue'}} >
    <h1>Page 2</h1>
    <Link to="/">Go Home</Link>
  </div>

Note: Pages also can be in sub directory

Interactive Pages

Create a file called src/pages/counter.js.

import React from "react"

class Counter extends React.Component {
  constructior() {
    super()
    this.state = { count: 0 }
  }
  render() {
    return
      <div>
        <h1>Counter</h1>
        <p>current count: {this.state.count}</p>
        <button onClick={() => this.setState({ count: this.state.count + 1})}>plus</button>
        <button onClick={() => this.setState({ count: this.state.count - 1})}>minus</button>
      </div>
  }
}

Building site

npm run build

The site will be built in folder public.

Components

Import a component in another page, such as index.js

import React from "react"
import Link from "gatsby-link"
import Counter from "./counter.js"

export default() =>
  <div style={{color: 'tomato', backgroundColor: 'blue'}} >
    <h1>Hello world!</h1>
    <p>This is a paragraph</p>
    <Link to="/page-2/">Page 2</Link>

    <Counter />
  </div>

Component Parameters

In index.js file

<Counter color="blue" />

Read parameter in counter.js.

{this.props.color}

or

<div style={{ clor: this.props.color}}>
  ...
</div>

Plugins

Plugins can be downloaded from https://www.gatsbyjs.org/docs/plugins

For example, install typography plugin

npm install --save gatsby-plugin-typography

Create gatsby-config.js file.

module.exports = {
  plugins: [`gatsby-plugin-typography`]
}

Then restart website

gats develop

Layouts

Create default layout in src/layouts/index.js

import React from "react"

export default({ children }) =>
  <div>
    <h1>Header</h1>
    {children()}
    <h3>Footer</h3>
  </div>

Site Data

Create a file called gatsby-config.js.

  module.exports = {
    siteMetadata: {
      title: "Giraffe Academy's Website",
      author: Mike,
    }
  }

In index.js, use graphql

import React from "react"

export default({data}) => (
  <div style={{color: 'tomato', backgroundColor: 'blue'}} >
    <h1>{data.site.siteMetadata.title}</h1>
    <p>{data.site.siteMetadata.author}</p>
  </div>
)

export const query = graphql`
  query FirstQuery {
    site {
      siteMetadata {
        title
        author
      }
    }
  }
`

Restart gatsby server.

Testing GraphiQL page

Access http://localhost:8000/___graphql

{
  site {
    siteMetadata {
      title
      author
    }
  }
}

File Data

Install gatsby-source-filesystem plugin

npm install --save gatsby-source-filesystem

Update gatsby-config.js

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `src`,
        path: `${__dirname}/src/`,
      }
    }
  ]
}

Restart gatsby server.

Use GraphiQL to query file or allFile

{
  allFile {
    edges {
      node {
        id
      }
    }
  }
}

Note: after key in allFile, press Control-Enter or Command-Enter, the information will be auto filled up.
Note: If delete id, press Control-Space, the available attributes will be shown.

For example,

node: {
  extension
  relativePath
}

Update index.js

import React from "react"

export default({data}) => (
  <div style={{color: 'tomato', backgroundColor: 'blue'}} >
    <table>
      <thead>
        <tr>
          <th>relativePath</th>
          <th>prettySize</th>
          <th>extension</th>
          <th>birthTime</th>
        </tr>
      </thead>
      <tbody>
        {data.allFile.edges.map({ node }) =>
          <tr>
            <td>
              {node.relativePath}
            </td>
            <td>
              {node.prettySize}
            </td>
            <td>
              {node.extension}
            </td>
            <td>
              {node.birthTime}
            </td>
          </tr>
        }
      </tbody>
    </table>
  </div>
)

export const query = graphql`
  query MyFilesQuery {
    allFile {
      edges {
        node {
          relativePath
          prettySize
          extension
          birthTime(fromNow: true)
        }
      }
    }
  }
`

Working with Markdown

Install plugin gatsby-transformer-remark

npm install --save gatsby-transformer-remark

Update plugin session in gatsby-config.js

module.exports = {
  plugins: [
    `gatsby-transformer-remark`,
  ]
}

In GraphiQL, can see two new options

markdownRemark
allMarkdownRemark

Create markdown file src/pages/myFirstPost.md

---
title: "My Markdown File"
author: "Mike"
---

This is the content in my markdown

To access attributes in markdown file

id
html
formatmatter
formatmatter {
  title
  date
  parent
}

References

Gatsby - Static Site Generator | Tutorial

Learning – Hexo – Static Site Generator

Learning - Hexo - Static Site Generator

Installation

Install NodeJS and git.

node -v
git version

Install Hexo

npm install -g hexo-cli
hexo -v

Init project

hexo init ga-hexo

This will create a folder called ga-hexo.

Run

cd ga-hexo
hexo server

The server will be run as http://localhost:4000.

Directories

node_modules - used by NodeJS
scaffolds - content templates
source - content folder
source/_post - the posts
themes - themes used
themes/landscape - default theme
_config.yml - define default theme, etc.
.gitignore
db.json
package.json - used by NodeJS package

Write content

Create post

Posts are written in source/_post.

cd ga-hexo
hexo new <page_name>

This will create a file source/_post/<page_name>.md

Create draft

hexo new draft <page_name>

This will create a file source/_draft/<page_name>.md. To show draft in hexo server, run following command

hexo server --draft

Publish draft

hexo publish <page_name>

Create page

hexo new page <page_name>

This will create a folder with index.html file source/<page_name>/index.md. To show page in hexo server, access URL http://localhost:4000/<page_name>/

Default type of page

The default layout can be found in _config.yml file as below

default_layout: post

If modify it as below,

default_layout: draft

Then the following command will create draft

hexo new <page_name>

Front Matter

Can be YAML or JSON

title: A's Title
date: 2017-09-14 15:11:10
tags: [ Tag1, Tag2, Tag3 ]

Scaffolds

In scaffolds folder, has 3 files as template, draft.md, page.md and post.md.

For example the post.md file.

---
title: {{ title }}
date: {{ date }}
tags:
---

Default content

Custom scaffold file

For example scaffolds/giraffee.md

title: {{ title }}
date: {{ date }}
layout: {{ layout }}

Following command

hexo new griaffe f

Will create following file

title: f
date: 2017-09-14 15:11:10
layout: griaffe

Tags & Categories

Tags

tags: [ Tag1, Tag2, Tag3 ]

The page will be

http://localhost:4000/tags/Tag1/

Categories

Categories:
- [Cat1, Cat1.1]
- [Cat2]
- [Cat3]

Tag Plugins

{% codeblock lang:javascript %}
  alert("Hello world");
  var myVar = "Hello World";
{% endcodeblock %}
{% youtuble hY7m5jjJ9mM %}

Asset Folders

The asset folders are static file folders.

To use asset folders, set following line in _config.yml file.

post_asset_folder: true

When run following command, source/_posts/a.md and source/_posts/a/ are created.

hexo new a

To use asset, following statement can be used in markdown file

{% asset_img hexo.jpg Hexo Logo %}

Note: Hexo Logo is the title of image.

To link to asset, use following line

{% asset_link hexo.jpg Hexo Logo %}

To use image path, use following line

{% asset_path hexo.jpg %}

Theme

Install theme

Themes can be downloaded from https://hexo.io/themes/index.html.

Then change _config.yml file as below

theme: alpha-dust

Restart the hexo server.

Create own theme

  • Create folder themes/ga-theme

  • Create file themes/ga-theme/config.yml

  • Create folders

themes/ga-theme/languages
themes/ga-theme/layout
themes/ga-theme/scripts
themes/ga-theme/source
  • Modify _config.yml file
theme: ga-theme
  • Restart hexo server

A blank page will be displayed.

Layout

layout.ejs

Layout is in themes/ga-theme/layout.

  • Create a file called layout.ejs in layout folder.
<html>
...
<body>
  This is the layout.ejs file
  <br>
  <%- body %>
  <br>
  This is the layout.ejs file
</body>
</html>

index.ejs

  • Create another file called index.ejs in layout folder.
This is a index.ejs file.

Then the output will be as follow for all index files, such as http://localhost:4000/, http://localhost:4000/a/, http://localhost:4000/2017/09/13/a/, etc.

This is the layout.ejs file
This is a index.ejs file.
This is the layout.ejs file

So all the pages will use layout.ejs file. And the <%- body %> will be replaced by actual ejs file. In above case, it is index.ejs file.

post.ejs

Create a file called themes/ga-theme/layout/post.ejs

<h1>This is a post</h1>

This will be used for all posts.

page.ejs

Create a file called themes/ga-theme/layout/page.ejs, this will impact all pages.

<h1>This is a page</h1>

tag.ejs

<h1>This is a tag</h1>

category.ejs

Partials

  • Create a folder themes/layout/partial

  • Then create a header.ejs in partial folder.

<h1><%= title %></h1>
<hr> <br>
  • In layer.ejs file
<html>
...
<body>
  <%- partial('partial/header', {title: 'hello world'}) %>
  <br>
  <%- body %>
  <br>
  Footer
</body>
</html>

Variables

Access front matter variable inside layout. For example, in post.ejs

<h1><%- page.title %></h1>
<p><%- page.date %></p>
<hr>
<%- page.content %>

The variables can be found in https://hexo.io/docs/variables.html

Custom variable

<%- page.author %>

If statement

<% if (page.author == "Mike") { %>
  Mike is the author, he's the best
<% } else { %>
  this author sucks
<% } %>

For Loops

<% site.posts.forEach(function(post) { %>
  <li><a href="<%- post.path %>"<%- post.title %></a></li>
  <br>
<% }) %>

Helper

Helpers are small functions.

<%- trim('    This is my string   ') %>
<%- titlecase('This is my string') %>
<%- date(Date.now(), 'YYYY/M/D') %>
<%- date(Date.now(), 'h:mm:ss a') %>

Helps can be found in https://hexo.io/docs/helpers.html.

Data Files

Create folder source/_data, and data file can be JSON or YAML file. Such as myData.yml

var1: "Var1's Value"
var2: "Var2's Value"
var3: "Var3's Value"

In template, such as index.ejs

<%- site.data.myData.var1 %> <br>
<%- site.data.myData.var2 %> <br>
<% for (var value in site.data.myData) { %>
  <%- value %> <br>
<% } %>
<br>
<% for (var value in site.data.myData) { %>
  <%- site.data.myData[value] %> <br>
<% } %>

Plugins

Download from https://hexo.io/plugins/.

Normally, use npm install to install plugin. For example,

npm install hexo-admin

After installed, go to _config.yml, make sure that plugin is listed in dependencies.

Generating Site

Run following command to generate website

hexo generate

The site will be created in public folder.

References

Hexo - Static Site Generator

iSCSI service failed after do-release-update

iSCSI service failed after do-release-update

The issue was caused by missing iscsi driver.

Errors

  • iscsid.service

Got following error

Oct 28 16:45:03 ubuntupi iscsid[6813]: can not create NETLINK_ISCSI socket [Protocol not supported]
  • iscsid.socket
     Active: failed (Result: service-start-limit-hit) since Thu 2021-10-28 16:40:07 +08; 1min 30s ago
  • depmod -a

Don't have iscsi module loaded

  • Error in dmesg
open-iscsi.service - Login to default iSCSI targets

    Process: 2333 ExecStart=/sbin/iscsiadm -m node --loginall=automatic (code=exited, status=21)