我正在参与「掘金启航计划」

Deps在准备好NewPathSpec,NewSpec,NewContentSpec,NewSourceSpec后,调用onCreate正式创立HugoSites,并在终究一步,加载模板履行器。

模板履行器只是提前将模板信息转化成了模板履行器,怎么运用并没有涉及到。

为了让咱们对模板生命周期有更全面的了解,让咱们以robots.txt为例,来看看是怎么经过模板履行器生成终究文件的。

了然于胸 – newTemplateExec时序图

Hugo站点渲染之模板词法解析

从时序图中,能够了解到创立履行器,首要分两步。

先创立包含了各种功用函数的executor。 其间的功用函数由两部分组成,一部分来自hugo,像htmlEscape等。 另一部分来自于golang的内置函数,如fmt.Sprint等等。 正是由于有这些功用函数的支撑,才得以让模板的action块 – ‘{{}}‘功用如此强壮。

履行器创立好后,接下来就要创立模板的handler了。 处理器供给了模板加载、查询等相关的服务,以便利运用。 由于查询服务依赖于加载服务,所以在处理器实例后,紧接着便是加载模板了。 而模板又分两部分,一部分是由hugo供给的默认模板,像robot.txt等。 另一部分便是由用户所供给的layouts文件,有来于主题的,也有来于用户自定义的layout。

加载的是磁盘文件,得到的是解析过后的模板实例。

templ, err := prototype.New(info.name).Parse(info.template)

源码里用的是prototype,而不是直接用的html。 这是由于咱们的模板有两种后缀,一种是txt,另一种是html,需求找到相应的原型来对模板进行解析。

不管是什么模板,都是文本,HTML也不例外,也是文本。 HTML模板的源码也应证了这一点 – 直接调用文本模板的办法。 那这种联系是怎么用代码完成的呢?

拿到模板字节信息后,用词法剖析器对模板字节流进行解析,得到剖析好的词义结构。 关于HTML模板而言,为了安全,需求对词义结构进行检查和必要地修改。 由于咱们能够从不同渠道,取得不同的主题,这些主题中又包含了许多模板,并且主题中能够嵌套主题,为了保证安全,避免履行恶意代码。 终究便是履行解析好的模板。

为了便利了解,咱们来举个比如 – robot.txt模板运用流程:

Hugo站点渲染之模板词法解析

  1. 查找:经过姓名查找,调用templateExec中的handler查询办法LookupLayout进行查询。
  2. 履行:准备履行模板所需求的信息,调用templateExec中的executor履行办法ExecuteWithContext开端履行。 这里的履行办法实际上也是由text template供给的,前面咱们也提到了,不管是什么类型的模板,都是以text为基础的。

知道了作业流程后,让咱们从源码层面,更深化的对Template进行了解。

咱们先来看第一步: 模板解析。

词法解析 – parse

Hugo站点渲染之模板词法解析

创立Deps的终究一步是loadResources,其间首要指的是Template资源。 在创立templateExec实例的过程中,就需求加载hugo默认和用户创立的模板。 加载模板后,获取了模板的字节信息,要想为咱们所有,首先要读懂这些字节,这时,咱们就用到了解析Parse,并且是由text模板供给的。 Parse为什么能够读懂这些字符信息呢,她依托的是内部了词法剖析器lex – lexer,剖析器需求对action block的语义有充分的了解。 读懂后转化为便利后续操作的数据结构tree,在hugo中实际载体是listNode类型。

咱们拿一段模板举个比如:

Hugo站点渲染之模板词法解析

从上例中,咱们能够看到,左上方是输入的信息。 包含一篇博客 – post.md,和一个模板 – single.html。 经过转化会得到最右边的输出网页内容。 其间,包含在模板中第一行的信息,剩下的是由博客供给的信息,其间的特别字符,还被进行了转义。

在左下方第一步中,创立templateExec过程中,读取到了模板single.html。 经过解析,利用词法剖析器,会得到如下状况:

[“<p><!-- HT…”, “{{”, “ “, ”.Content”, ” “, ”}}”, EOF]

为了了解其间的作业原理,让咱们在下一章节中一起来看一下action block的词法剖析器是怎么作业的。