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

目录
  • 正文
  • 了然于胸 - newTemplateExec时序图
  • 词法解析 - parse

正文

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

模板执行器只是提前将模板信息转换成了模板执行器,如何使用并没有涉及到。

为了让我们对模板生命周期有更全面的了解,让我们以robots.txt为例,来看看是如何通过模板执行器生成最终文件的。

了然于胸 - newTemplateExec时序图

从时序图中,可以了解到创建执行器,主要分两步。

先创建包含了各种功能函数的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模板使用流程:

  • 查找:通过名字查找,调用templateExec中的handler查询方法LookupLayout进行查询。
  • 执行:准备执行模板所需要的信息,调用templateExec中的executor执行方法ExecuteWithContext开始执行。 这里的执行方法实际上也是由text template提供的,前面咱们也提到了,不管是什么类型的模板,都是以text为基础的。

知道了工作流程后,让我们从源码层面,更深入的对Template进行理解。

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

词法解析 - parse

创建Deps的最后一步是loadResources,其中主要指的是Template资源。 在创建templateExec实例的过程中,就需要加载hugo默认和用户创建的模板。 加载模板后,获取了模板的字节信息,要想为我们所有,首先要读懂这些字节,这时,我们就用到了解析Parse,而且是由text模板提供的。 Parse为什么可以读懂这些字符信息呢,她依靠的是内部了词法分析器lex - lexer,分析器需要对action block的语义有充分的理解。 读懂后转换为方便后续操作的数据结构tree,在hugo中实际载体是listNode类型。

我们拿一段模板举个例子:

从上例中,我们可以看到,左上方是输入的信息。 包含一篇博客 - post.md,和一个模板 - single.html。 通过转换会得到最右边的输出网页内容。 其中,包含在模板中第一行的信息,剩下的是由博客提供的信息,其中的特殊字符,还被进行了转义。

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

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

为了理解其中的工作原理,让我们在下一章节中一起来看一下action block的词法分析器是如何工作的。

以上就是go开源Hugo站点渲染之模板词法解析的详细内容,更多关于Hugo站点渲染模板词法的资料请关注我们其它相关文章!

(0)

相关推荐

  • go开源Hugo站点构建三步曲之集结渲染

    目录 Assemble PageState 动手实践 - Show Me the Code of Create a PageState Render 动手实践 - Show Me the Code of Publish Assemble Assemble所做的事情很纯粹,那就是创建站点页面实例 - pageState. 因为支持多站点,contentMaps有多个. 所以Assemble不仅要创建pageState,还需要管理好所有的pages,这就用到了PageMaps. type pageM

  • 详解无界微前端是如何渲染子应用的demo解析

    目录 正文 无界渲染子应用的步骤 创建子应用 iframe 解析入口 HTML 处理 CSS 并重新嵌入 HTML 创建 webComponent 并挂载 HTML JS 的执行细节 简单的实现 将 UI 渲染到 shadowRoot 挟持 document 的属性/方法 副作用的处理 DOM 相关的副作用处理 修正相对 URl 修正 shadowRoot head.body iframe 的副作用处理 History API window/document 属性/事件 location 对象

  • 通过示例源码解读React首次渲染流程

    目录 说明 题目 首次渲染流程 render beginWork completeUnitOfWork commit 准备阶段 before mutation 阶段 mutation 阶段 切换 Fiber Tree layout 阶段 题目解析 总结 说明 本文结论均基于 React 16.13.1 得出,若有出入请参考对应版本源码.参考了 React 技术揭秘. 题目 在开始进行源码分析前,我们先来看几个题目: 题目一: 渲染下面的组件,打印顺序是什么? import React from

  • React中immutable的UI组件渲染性能详解

    目录 引言 UI组件渲染性能 方案一:shallow compare 方案二:直接对前后的对象进行deepCompare 总结: 引言 react 一直遵循UI = fn(state) 的原则,有时候我们的state却和UI不同步 有时候组件本身在业务上不需要渲染,却又会再一次re-render.之前在项目中遇到的一些问题,这里做一个简单的分析,大家可以一起交流一下 UI组件渲染性能 react每次触发页面的更新可大致分成两步: render(): 主要是计算v-dom的diff commit阶

  • electron渲染进程主进程相互传值示例解析

    目录 在electron中分为渲染进程和主进程 浏览器传值给主进程 浏览器环境 主进程 主进程传值给渲染进程 主进程 渲染进程 注意 在electron中分为渲染进程和主进程 渲染进程就是浏览器环境,主进程就是node环境 既然他们是不同的环境,那么为我们怎么让他们相互关联起来呢?或者说怎么传递值? 毕竟在开发中可能会遇到我想要的值只能在node环境中才能获取,然后node中可能也会需要浏览器环境的值:这个时候就需要两个环境联通起来相互传值 浏览器传值给主进程 浏览器环境 引入: import

  • flask框架渲染Jinja模板与传入模板变量操作详解

    本文实例讲述了flask框架渲染Jinja模板与传入模板变量操作.分享给大家供大家参考,具体如下: 1. 模板简介 模板是一个web开发中必备的模块,因为我们在渲染一个网页的时候,并不只是渲染了一个纯文本字符窜,而是渲染一个有富文本标签的页面,这个时候我们就需要用到模板了.在flask中,配套的模板是Jinja2,Jinja2的作者也是flask的作者. 2. flask中渲染模板 在flask中,如果我们需要渲染一个模板,那么我们就需要用到render_template这个方法了. 在我们新建

  • vue2从数据到视图渲染之模板渲染详解

    目录 引言 1.从new Vue()入口开始: 2.this._init 3.挂载函数vm.$mount(vm.$options.el) 4.mountComponent函数 5._render函数 6.createElement函数返回虚拟DOM 7._update函数 8.patch函数 9.createElm函数 10.移除 引言 一般使用html,css和javascript直接将数据渲染到视图中,需要关心如何去操作dom,如果数据量比较大,那么操作过程将会繁琐且不好控制.vue将这些操

  • Thinkphp模板没有解析直接原样输出的解决方法

    本文实例讲述了Thinkphp模板没有解析直接原样输出的解决方法.分享给大家供大家参考.具体如下: 一.问题: 最近在学习thinkphp模板了,但是发现模板页原样出来了,经过一番艰苦搜索终于找到解决方案. 二.解决方法: 很多人都碰到相同问题,在变量中赋值的字符串中包含的__ROOT__.__PUBLIC__.__APP__,这种字符的, 在模板中display出来的时候都被替换成了真实路径.话说是在写Timi文件管理系统的时候发现的这个问题. 从文件中把源码读出来输出到页面后发现,只要是TP

  • ThinkPHP让../Public在模板不解析(直接输出)的方法 原创

    本文实例讲述了ThinkPHP让../Public在模板不解析的方法.分享给大家供大家参考.具体如下: 问题: 模板中包含../Public需要直接输出,但是../Public会被直接替换为当前公共模板目录,最终输出为:/项目目录/Tpl/default/Public/ 解决方法: 在配置文件config.php中添加模板常量设置: 'TMPL_PARSE_STRING' => array( '../Public' =>"../Public", ) // 模板引擎要自动替换

  • 获取站点的各类响应时间(dns解析时间,响应时间,传输时间)

    有时候为了测试网络情况,需要返回每个阶段的耗时时间,比如DNS解析耗时,建立连接所消耗的时间,从建立连接到准备传输所使用的时间,从建立连接到传输开始所使用的时间,整个过程耗时,下载的数据量,下载速度,上传数据量,上传速度等等.下面的脚本获取以上信息: CURL的资料参见: http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html 复制代码 代码如下: ###################################### author: ww

  • SpringBoot FreeWorker模板技术解析

    这篇文章主要介绍了SpringBoot FreeWorker模板技术解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.添加依赖 <!--模板依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> &

  • SpringBoot使用thymeleaf模板过程解析

    这篇文章主要介绍了SpringBoot使用thymeleaf模板过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.导入依赖 <!-- 添加thymeleaf模版的依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</art

  • Android Shader着色器/渲染器的用法解析

    一.介绍 Shader是绘图过程中的着色器,它有五个子类: BitmapShader: 位图渲染 LinearGradient: 线性渲染 SweepGradient: 梯度渲染 RadialGradient: 光束渲染 ComposeShader: 组合渲染 渲染模式:Shader.TileMode Shader.TileMode.CLAMP: 边缘拉伸模式,它会拉伸边缘的一个像素来填充其他区域. Shader.TileMode.MIRROR: 镜像模式,通过镜像变化来填充其他区域.需要注意的

  • C++ 类模板与成员函数模板示例解析

    目录 类模板 类模板与成员函数模板的区别 类模板 前面以函数模板为例,介绍了具体化与实例化.那么对于类模板,有什么不同呢? 类包括成员变量和成员函数,他们都可以包含类模板的模板参数.而成员函数本身也可以是函数模板.看下面的两个类: // 类模板 template <typename T> class A { private: T t; public: void funcA(T t); }; template <typename T> void A<T>::funcA(T

随机推荐