因为最近在写 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,可以直接用这个类库。而不是自己写正则处理。