Skip to content

从 Hexo 迁移到 Hugo #11

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
nodejh opened this issue Nov 22, 2016 · 10 comments
Open

从 Hexo 迁移到 Hugo #11

nodejh opened this issue Nov 22, 2016 · 10 comments

Comments

@nodejh
Copy link
Owner

nodejh commented Nov 22, 2016

把博客从 Hexo 迁移到了 Hugo。主要原因有二:

  • Hexo 中文乱码。当中文大概超过1000字,就出现奇怪的乱码。看了 Hexo 的 ISSUE,这个问题也不只我遇到。
  • Hexo 生成静态文件太慢了,等上十几二十秒是常有的事。

遂弃用 Hexo。

1. 将 Hexo 的 YAML 转换为 Hugo 的 TOML

Hugo 的配置文件是 TOML 格式的,其生成的 Markdown 文件的 front matter(不知如何翻译)也是 TOML 结构:

+++
date = "2016-09-30T17:14:37+08:00"
description = ""
title = "Migrate to Hugo from Hexo"
tags = ["hugo", "hexo", "blog"]

+++

而 Hexo 的配置文件是 YAML 格式,其 Markdown 文件的 front matter 如下:

title: 'Start React with Webpack'
date: 2016-09-09 04:11:13
tags:
  - webpack
  - react

---

所以直接将 Hexo 的 Markdown 文件复制到 Hugo 中是不行的,必须得转换一下格式。虽然 Hugo 也可以直接在 config.toml 中配置 metaDataFormat:"yaml",这样 Hugo 就会生成 YAML 结构的 front matter ,但原 Hexo 的 Markdown 文件依旧不能正常的转换,因为 date 的格式不一样。

在 Hexo 中,文件里面的 date: 2016-09-09 04:11:13 并没有存储时区信息,而是把时区放在了 _config.yml 配置文件中。

By the way,TOML 是 GitHub 觉得 YAML 不够简洁优雅,所以捣鼓出来的一个东西。既然现在在用 Hugo,就没有理由不用 TOML 代替原来的 YAML。

其实两者之间的转换也很简单,我用 JS 写了一个脚本来将 YAML 转换为 TOML:

// yaml_to_toml.js
const readline = require('readline');
const fs = require('fs');
const os = require('os');
const moment = require('moment-timezone');  // 需要通过 npm install moment-timezone 来安装


const timezone = 'Asia/Shanghai';  // 时区
const src = 'hexo';  // hexo .md 文件源目录
const target = 'post';  // 目标文件目录


// 开始转换
readDir();


// 遍历目录
function readDir() {
    // read all files in src
    fs.readdir(src, function(err, files) {
        files.map((filename) => {
            // get the file extension
            const extension = filename.substr(filename.lastIndexOf('.', filename.length));
            if (extension === '.md') {
              readFile(`${filename}`);
            }
        });
    });

}


function readFile(filename) {
  fs.readFile(`${src}/${filename}`, { encoding: 'utf8' }, function(err, data) {
      if (err) {
          return console.log('err: ', err);
      }

      const content = data.split('---');
      const head = content[0].split('\n');
      // console.log('head: ', head);

      let newHead = head.map((item, index) => {
        // console.log('slpitHead: ', slpitHead(item, index, head));
        return slpitHead(item, index, head);
      });
      newHead = newHead.filter((item) => {return item;});
      // console.log('newHead: ', newHead);
      const newContent = `+++${os.EOL}${newHead.join(os.EOL)}${os.EOL}${os.EOL}+++${os.EOL}${content[1]}`;
      fs.writeFile(`${target}/${filename}`, newContent, {
          encoding: 'utf8'
      }, function(err) {
          if (err) {
            throw err;
          }
          console.log(`${filename}  生成成功!`);
      });
  });
}



function slpitHead(item, index, head) {
  // title
  if (item.indexOf('title:') !== -1) {
    return `title = "${item.split('title:')[1].trim()}"`;
  }

  // date
  if (item.indexOf('date:') !== -1) {
    return `date = "${(moment.tz(item.split('date:')[1], timezone)).format()}"`;
  }

  // tags
  if (item.indexOf('tags:') !== -1) {
    // console.log('tags...');
    const tags = [];
    for (let i=index+1; i<head.length; i++) {
      if (head[i].indexOf('-') !== -1) {
        // console.log('head[i].split('-')[1]: ', head[i].split('-')[1]);
        tags.push(head[i].split('-')[1].trim());
      } else {
        break;
      }
    }
    // console.log('tags: ', tags);
    return `tags = ${JSON.stringify(tags)}`;
  }

  // categories
  if (item.indexOf('categories:') !== -1) {
    const categories = [];
    for (let i=index+1; i<head.length; i++) {
      if (head[i].indexOf('-') !== -1) {
        categories.push(head[i].split('-')[1].trim());
      } else {
        break;
      }
    }
    // console.log('categories: ', categories);
    return `categories = ${JSON.stringify(categories)}`;
  }

  return false;
}

先配置好 timezone src target 三个参数。然后 npm install moment-timezone 安装需要的第三方包,最后 node yaml_to_toml.js 即可。

2. 图片目录的迁移

本地图片迁移也非常简单。

我之前使用 Hexo 的时候,是将所有图片都放在 source/images/ 目录里面的,在 Markdown 文件中引入图片是这样的: ![image title](/iamges/image_name.png)

Hugo 的图片可以直接放在其 static/ 目录里面,其路径就是 /iamges/image_name.png,所以我只需要将 Hexo 中的 images 目录复制到 Hugo 的 static/ 目录下即可。

3. 主题

看遍了 Hugo 给出的所有主题,都不满意。很多主题都超级简洁,这种风格还是很喜欢的。所以决定自己写一个。

最终 Fork 了 https://github.com/digitalcraftsman/hugo-cactus-theme 这个主题,然后改成了自己想要的样子。

主页

Migrate-to-Hugo-from-Hexo-1.png

文章页

Migrate-to-Hugo-from-Hexo-2.png

改后的主题源码:https://github.com/nodejh/hugo-theme-cactus-plus

4. 部署

由于 Github Pages 国内访问速度慢,所以同时把静态页面部署到了 Github Page 和 Coding Pages。

// 添加两个仓库
git remote add all https://github.com/nodejh/nodejh.github.io
git remote set-url origin --push --add https://git.coding.net/nodejh/nodejh.git
git remote set-url origin --push --add https://github.com/nodejh/nodejh.github.io

然后只需要执行 git push all branch 就可以同时向两个仓库 push 代码了。但暂时不这样做。而是在 public 目录外创建一个 deploy.sh 目录,用来自动部署:

#!/bin/bash

echo -e "\033[0;32mDeploying updates to GitHub...\033[0m"

# Build the project.
hugo # if using a theme, replace by `hugo -t <yourtheme>`

# Go To Public folder
cd public
# Add changes to git.
git add -A

# Commit changes.
msg="rebuilding site `date`"
if [ $# -eq 1 ]
  then msg="$1"
fi
git commit -m "$msg"

# Push source and build repos.
git push origin master

# Come Back
cd ..

接下来再给 deploy.sh 添加可执行权限 chmod +x deploy.sh。然后每次写完东西只需要 ./deploy.sh 'commit message' 即可。

@gnostr
Copy link

gnostr commented Feb 28, 2017

你好。请问用nginx + hugo + 这个主题,为什么生成的页面没有css? 谢谢

@nodejh
Copy link
Owner Author

nodejh commented Feb 28, 2017

写完 markdown 之后,使用 hugo 命令,就会根据 config.toml 中配置的主题生成对应的静态资源文件(包括 html/css/js)。静态资源文件在 public 目录。使用该主题生成的资源文件列表如下:

70e51c47-43b2-4509-b514-c2f68aff7220

所以我猜测可能原因有两个

  • 一是是否使用的 hugo 命令。因为 hugo server 不会编译出静态文件,而是将编译结果放在内存
  • 二是是否指定了主题

@gnostr
Copy link

gnostr commented Feb 28, 2017

谢谢回复!

有css文件,
screen shot 2017-02-28 at 10 57 43

config.toml中也有指定theme

网页加载还是这样
screen shot 2017-02-28 at 10 58 06

@nodejh
Copy link
Owner Author

nodejh commented Feb 28, 2017

那应该是 config.tomlbaseurl 设置的问题了。

hugo 生成的 html 文件中,所有的链接都是根据 baseurl 生成的绝对路径(带域名的)。比如 baseurl = "http://nodejh.com",则在 index.html 中生成的路径就是 http://nodejh.com/js/main.js

所以根据你的服务器环境,修改一下 config.tomlbaseurl ,应该就能解决问题。

@gnostr
Copy link

gnostr commented Feb 28, 2017

还是不行。。我试了另外一个theme,没有问题。我也很是困惑... anyway,谢谢你,很可惜用不了这个theme!

CentOS 7 + Vultr

@xinx1n
Copy link

xinx1n commented Feb 7, 2018

能否添加对 gitalk 评论系统的支持?

@94192448
Copy link

config.toml 中文乱码,有设置地方吗?

@binhaifgs1
Copy link

config.toml 中文乱码,有设置地方吗?

找到办法了吗

@nodejh nodejh removed blog labels Nov 28, 2019
@iamwlb
Copy link

iamwlb commented Apr 10, 2020

node yaml_to_toml.js ─╯
/Users/iamwlb/Documents/Workspace/nodejs/yaml_to_toml.js:21
files.map((filename) => {
^

TypeError: Cannot read property 'map' of undefined

@tianheg
Copy link

tianheg commented Apr 29, 2020

node yaml_to_toml.js ─╯
/Users/iamwlb/Documents/Workspace/nodejs/yaml_to_toml.js:21
files.map((filename) => {
^

TypeError: Cannot read property 'map' of undefined

我也遇到了同样的问题,找了很久,找不到解决办法。有这类错误的,跟 React 相关的很多,可是我不了解它。不知道 JavaScript 和 React 之间的联系

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants