Hexo 原理分析:hexo-front-matter

178 阅读2分钟

因为最近在写 Hexo 的客户端软件,所以不得不分析 Hexo 的一些原理,顺便记录一些笔记。

如标题的这个包,是一个很小的包,可以很容易地复用。

import yaml from 'js-yaml';
declare function split(str: string): {
    data: string;
    content: string;
    separator: string;
    prefixSeparator: boolean;
} | {
    content: string;
    data?: undefined;
    separator?: undefined;
    prefixSeparator?: undefined;
};
declare function parse(str: string, options?: yaml.LoadOptions): any;
declare function escapeYAML(str: string): string;
interface Options {
    mode?: 'json' | '';
    prefixSeparator?: boolean;
    separator?: string;
}
declare function stringify(obj: any, options?: Options): any;
export { parse, split, escapeYAML as escape, stringify };

这就是这个包的全部代码的声明,非常好理解。

首先,第一个工具函数是 split,可以将一个文本,分解成一个对象:

{
    data: string;
    content: string;
    separator: string;
    prefixSeparator: boolean;
}

第一个字段 data 是一个 front-matter 的字符串;

第二个字段 content 是文章的正文部分;

第三个字段 separator 是分隔符;注意,可以是 “---” 或者是 “;;;”

最后一个字段是说,这个分隔符是配对的,还是不配对。

代码逻辑里,基本就是用正则进行解析,也可能整个文档里就不含 front-matter,那么解出来的对象里,只有 content。

然后,是最重要的方法parse,从声明来看,返回值是一个 any,实际上,是一个 PlainObjcect,因为每个 key 是 front-matter 中指定的 key,所以对 key 是什么, 以及值是什么类型,不确定,所以声明为 any。

解析 json 用的是 parseJSON,解析 yaml 用的是 js-yaml 包里的 parseYAML,每个 front-matter 的字段,占一个对象的 key,最后,整个正文部分会占用一个字段是 _content。

这个parse 方法,会调用 split 先来拆解文档字符串,然后单独解析 data 字段,将得到的对象 obj 的 _content 字段赋值为内容:

    let data;
    if (splitData.separator.startsWith(';')) {
        data = parseJSON(raw);
    }
    else {
        data = parseYAML(raw, options);
    }
    if (!data)
        return { _content: str };
    // Convert timezone
    Object.keys(data).forEach(key => {
        const item = data[key];
        if (item instanceof Date) {
            data[key] = new Date(item.getTime() + (item.getTimezoneOffset() * 60 * 1000));
        }
    });
    data._content = splitData.content;

这是一个代码片段,可以看到,parse 最后给 parse 的结果的 _content 字段,赋值了 split 方法得到的 content。

escapeYAML 是一个工具函数,在 parseYAML 里面会用到。其他场景,可能用不到。

最后,一个很重要的函数,是 stringify 是将 PlainObject 再还原回字符串。这里 options 参数可以指定是用 json 还是用 yaml,以及分隔符是否用 “---” 还是 “;;;”,以及是否要加开头的分隔符。

相对来说很简单,如果要分析 Hexo 下的文章,需要读取文章的 front-matter,可以直接用这个类库。而不是自己写正则处理。