hugo生成文章中不能正确显示中文字数的问题定位

问题发现

在刚切换到hugo博客的时候就发现文章的字数统计是错误的,但是因为当时也没发现有额外的副作用,就暂时懒得理了,毕竟这个只是写作工具,web前端也不是本人长项。

今天在使用多说分享文章的时候发现部分文章分享失败,于是根据分享生成的URL中的数据初步判断是获取文章content时出错了。插件获取了超长的content内容,导致接口调用失败。

问题定位

1. 多说

我们看多说插件中的相关代码:

data-content="{{ .Summary }}" 

多说只是使用了模版中的Summary变量值。

2. Summary

关于Summary变量,我们看Hugo的解释

Hugo-defined: automatic summary split

By default, Hugo automatically takes the first 70 words of your content as its summary and stores it into the .Summary variable, which you may use in your templates.

Pros: Automatic, no additional work on your part.
Cons: All HTML tags are stripped from the summary, and the first 70 words, whether they belong to a heading or to different paragraphs, are all lumped into one paragraph. Some people like it, but some people don't.

从以上的内容看到Hugo只是默认最多取70个词(words),所以这里很明显是取70个词时,实际取出了远远多于70个的内容,导致上面的url出错。

3. 长度错误

从上面我们初步判断是长度的问题。初步查看模版的代码,我们知道长度在模版中使用的是WordCount变量。于是我们查看hugo中WordCount相关的代码hugolib/page.go:

if p.isCJKLanguage {
        p.WordCount = 0
        for _, word := range p.PlainWords() {
            runeCount := utf8.RuneCountInString(word)
            if len(word) == runeCount {
                p.WordCount++
            } else {
                p.WordCount += runeCount
            }
        }
    } else {
        p.WordCount = len(p.PlainWords())
    }

从上面isCJKLanguage的变量名我们就能猜到是判断非英文的路径。简单看下代码,Hugo是有考虑CJKLanguage的问题的,也就是说可能是这个分支没有执行。

4. isCJKLanguage

我们搜索工程,找到isCJKLanguage:https://github.com/spf13/hugo/blob/2c5e4f7640e71d2a193a74e6c41109ec40bc0222/docs/content/content/front-matter.md 中的介绍,于是手动在出错的markdown文件中添加此变量,再次重新执行hugo,发现对应生成的网页中的字数统计的值正确了,分享也不出错了,说明就是字数的统计导致了系统错误。

问题验证了,但是因为博客的文章都是用工具自动从wordpress中生成的,不可能手动一个一个修改,修改工具也显得很死板,最好的方法是从Hugo这侧来找方案。

5. hugo配置文件

顺着上面的思路,开始搜索相关的关键字,发现hugo的配置中还真有相关的配置hasCJKLanguage:https://github.com/spf13/hugo/blob/b7efbdc12f0a96639b445f7920b6477d88beb744/docs/content/overview/configuration.md ,喜出望外,赶紧添加到config文件中重新编译文件,编译后发现并没有生效。于是再次查看源码hugolib/page.go:

if isCJKLanguage != nil {
        p.isCJKLanguage = *isCJKLanguage
    } else if viper.GetBool("HasCJKLanguage") {
        if cjk.Match(p.rawContent) {
            p.isCJKLanguage = true
        } else {
            p.isCJKLanguage = false
        }
    }

从上面的代码看isCJKLanguage 是由HasCJKLanguage开关控制的。

6. HasCJKLanguage

继续看代码,我们看到工程中只有一个地方有设置commands/hugo.go:

viper.SetDefault("HasCJKLanguage", false)

于是尝试修改本地的此行代码,重新编译Hugo。再次用hugo生成所有文章,发现所有文章的长度都正确了,甚是高兴。

再次检查今天发现的分享出错的文章,都全部正常了,舒服!

一键迁移wordpress到hugo

网站已经迁移了一个多月,一直想写下,但是因为一个issue的问题,一直不爽快:
the tag format
一直想等待解决再来写。

周末抽空过了一遍代码,代码中是用spyc来生成yaml的。改成[xx, x] 的格式还是要费点神的,而且破坏了原来格式的简单优美,什么意思?看下两种格式的生成就明白了,前者是不用考虑长度的迭代模式,后者要考虑长度,因为要在结尾加后括号']',这样逻辑就不是简单流式的了。为了确认是否值得修改,确认了官方的文档:
yaml官方文档
发现2种格式都是支持的,但是hugo的问题是:
文档的tags和categories本质来讲,都是列表数组,没有道理两种采用不同的格式,详情:
the tag format advice
显然关闭的人并没有理解我的意思,但是还是有其他的开发者明白了我的意思,做了回复,总之此问题目前确认是属于hugo的“不优雅”。不打算勉强,为了修复而修复,静待hugo的变化吧。

hugo

hugo是一个能把markdown转化成静态html网站的工具。

wordpress-to-hugo-exporter

说了这么多,言归正传,一键切换主要是使用这个插件:
wordpress-to-hugo-exporter
这个插件功能是通过提取wp的页面,将所有的可见页面转换成markdown文档。

生成md文件

支持两种方式:
1. 在wp插件页面通过按钮执行
2. 在后台命令行通过cli方式执行:

php hugo-export-cli.php

前者的文件会导出到用户客户端,后者生成的.zip在/tmp目录下。

后继的工作

这个插件只是将wp的内容转化成markdown文档,要创建hugo网站,你需要:

  • 找一个你喜欢的theme,从hugo官网就能找到
  • 根据theme的指导,配置相应的config文件,每一个theme的config会有略微差异
  • 将之前的markdown打包文件根据你自己配置的目录层次解压到hugo的content目录下的对应路径中。
    如果以上你都做对了,你应该已经可以看到你的hugo网站了。
    相关参考:
    一步一步教你用hugo搭建博客

中文支持的PR

拿到插件时,是不支持中文路径的,含有中文路径的文章,都是404。这个对大陆用户来说很不方便的,因为有很多人的文章都是有中文路径的。于是提交了对应的PR:
fix the unicode url issue and markdown format error
作者很勤快,很快就合入了主干,所以现在大家可以直接使用主干的代码,就是支持中文了。

一步一步教你用hugo搭建博客

Hugo 是一个轻量级的静态网站生成工具,是基于GO语言的模版技术开发而成,因为最近在学习go,就花了时间研究了下,一研究就喜欢上了。
再加上最新wordpress版本有严重的问题,在文章发表后或者再次编辑时,编辑框会丢失所有的格式,这个让使用Markdown的人无法接受。

安装hugo

Hugo官方主页:HUGO
hugo托管在github上,我们可以直接二进制安装也可以源码安装。
这里我们演示源码安装。

  1. 源码安装
    在go里面我们可以直接通过get安装:
    go get -u -v github.com/spf13/hugo
    或者直接git下载
    git clone https://github.com/spf13/hugo.git

  2. 编译
    go build -o hugo main.go
    mv hugo $GOPATH/bin
    终端查看是否成功,mac下可能出现路径没找到的问题,要重新开终端
    $ hugo version
    Hugo Static Site Generator v0.16-DEV BuildDate: 2015-12-14T16:07:24+08:00

生成静态站点

  1. 创建网站
    我们先创建一个空网站.
    $ hugo new site localhost
    $ tree
    .
    ├── archetypes
    ├── config.toml
    ├── content
    ├── data
    ├── layouts
    ├── public
    ├── static
    └── themes  

默认情况下这些目录都是空的,直接运行的话会有ERROR提示

    ERROR: 2015/12/14   =============================================================
    ERROR: 2015/12/14 Your rendered home page is blank: /index.html is zero-length
    ERROR: 2015/12/14  * Did you specify a theme on the command-line or in your
    ERROR: 2015/12/14    "config.toml" file?  (Current theme: "")
    ERROR: 2015/12/14  * For more debugging information, run "hugo -v"
    ERROR: 2015/12/14 =============================================================

看提示说是没有指定theme导致,我们需要下载一个theme。

  1. 安装theme
    我们可以从hugo的网站下载自己喜欢的theme
    $ cd themes
    $ git clone https://github.com/spf13/hyde.git

  2. 测试框架
    安装完theme后,我们体验下效果,使用 hugo server就可以起一个http server,默认监听在1313端口,如果没有在config中配置theme,就要指定theme。

    $ hugo server -t hyde
    0 draft content
    0 future content
    0 pages created
    0 paginator pages created
    0 tags created
    0 topics created
    in 24 ms
    Watching for changes in /Users/alex/run/localhost/{data,content,layouts,static,themes}
    Serving pages from memory
    Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
    Press Ctrl+C to stop            

hyde 界面

  1. 发表文章
    hugo里面写文章其实就是写markdown文档了。写好文档,hugo会给你自动转成html静态文件。我们通过Hugo创建一个md文档。
    $ hugo new first.md
    /Users/alex/run/localhost/content/first.md created
    运行时在网站根目录下运行,创建的文件默认创建在content目录下。
    +++
    date = "2015-12-15T22:35:22+08:00"
    draft = true
    title = "first"
    
    +++

我们从内容看默认创建的是草稿类型,需要将draft改为true才能看到页面。正常情况下我们会通过Mou或者github编辑文档,只要文件头符合hugo的规范就可以。
第一篇文章

调试部署

  1. 调试
    在开发的过程中,我们需要不断的修改验证,所以hugo支持LiveReload功能,用户修改后,可以实时看到效果。执行hugo server命令时加上-w选项,hugo就可以自动检测本地站点文件的变更。
    $ hugo server -w -t hyde
    注意:在使用server命令时,hugo并没有在public目录下产生相应的静态页面。

  2. 部署
    部署时,我们需要生成静态页面文件,然后就可以随便部署在自己的空间上了。转化时,一个hugo命令就搞定:

    $ hugo -t hyde
    0 draft content
    0 future content
    1 pages created
    0 paginator pages created
    0 topics created
    0 tags created
    in 38 ms

我们看到有一个页面生成了,默认在public目录,实际一起生成的还有其他文件:

    $ ls
    404.html                first
    apple-touch-icon-144-precomposed.png    index.html
    css                 index.xml
    favicon.png             sitemap.xml

把这些文件放到你的空间,你就可以看见你的页面和theme了。

到这里,我们已经有了一个基本的能创建文章并且显示的网站了。

have fun!

通过event-hook将Github自动部署至Hugo网站

WHAT

hugo是一个轻量高效的博客系统,很适合个人博客。使用hugo,我们只要写作完markdown文档,就可以利用hugo工具,自动生成网页,
变成我们的网站。

我们理想的步骤:

  • 在github上写完markdown文章
  • 提交完后,数秒后就看见了我们的网站页面
  • 在github上修改完网站的配置文件,数秒后我们的网站就变化和更新了。

好爽!

流程

为了完成上面的效果,我们大概分为几步:

  1. 设置github的webservice hook。当完成一篇新的文章或者修改旧的文章后,github就会向目标网站发webservice hook消息。
  2. 目标网站收到消息后git pull,解析消息特征,更新相关的文档,最后调用hugo
  3. hugo将markdown文章转化成html静态页面
  4. 将html页面部署到目标web服务器

HOW

详细请移步:
https://github.com/hiproz/hugo-sync

分分钟就搞定了,一劳永逸!

have fun!

hugo-md文档书写时的格式说明

前言

在决定使用github-hugo自动化流程后,第一个面临的问题就是,这个文档头的格式到底是什么样的,因为现在你要手写,就需要彻底搞清楚, 以便达到正确和高效。

阅读查找了gohugo.io的所有相关页面,找到以下两个相关的内容基本上说的很清楚了:
https://gohugo.io/content/front-matter/
https://gohugo.io/content/archetypes/

头格式

md只是文档的类型,但是里面的内容遵循怎样的格式呢? hugo目前支持3中toml,yaml,json,三种格式的文件头。识别符号分别如下

  • toml: +++
  • yaml: ---
  • json: {}

toml示例:

+++
title = "spf13-vim 3.0 release and new website"
description = "spf13-vim is a cross platform distribution of vim plugins and resources for Vim."
tags = [ ".vimrc", "plugins", "spf13-vim", "vim" ]
date = "2012-04-06"
categories = [
  "Development",
  "VIM"
]
slug = "spf13-vim-3-0-release-and-new-website"
+++

Content of the file goes Here

yaml示例:

---
title: "spf13-vim 3.0 release and new website"
description: "spf13-vim is a cross platform distribution of vim plugins and resources for Vim."
tags: [ ".vimrc", "plugins", "spf13-vim", "vim" ]
date: "2012-04-06"
categories:
  - "Development"
  - "VIM"
slug: "spf13-vim-3-0-release-and-new-website"
---

Content of the file goes Here

json示例:

{
    "title": "spf13-vim 3.0 release and new website",
    "description": "spf13-vim is a cross platform distribution of vim plugins and resources for Vim.",
    "tags": [ ".vimrc", "plugins", "spf13-vim", "vim" ],
    "date": "2012-04-06",
    "categories": [
        "Development",
        "VIM"
    ],
    "slug": "spf13-vim-3-0-release-and-new-website",
}

Content of the file goes Here

字段变量

文档可以包含很多变量。

必要字段

  • tile: 内容的标题
  • description: 内容的描述
  • date:日期
  • taxonomies:分类字段,包括tag和categories

可选字段

  • aliases: 别名
  • draft: 是否是草稿
  • publishdate: 定时未来发布的时间
  • type: 内容的格式,可以从内容自动识别
  • isCJKLanguage:是否时CJK
  • weight: 排序的权重
  • markup: 时markdown格式还是reStructuredText
  • slug: url尾部的token
  • url: 完整的url

hugo markdown引擎的配置

finish!