Only by grasping the template in golang can we control the template of the Hugo theme

The author's small station: Qiuma record

Noncommittal, Hugothe templatesame is golangthe standard library used html/template. In order to realize a unique theme of your own Hugo theme, or to modify other people's themes, you have to 模板语法know about it, so that you can change it to your heart's content, or create a set that is both simple and elegant Hugo theme.

Create a golang project

Obviously, we must first create a golangproject before we can explain what is golanggoing on html/template. There is no doubt about this. After all, what we are playing now golangis golangthe standard library html/template.

Alright, enough gossip, let's get to the point. About golanghow to create a project, you should be relatively clear! Otherwise, you will not browse this article, of course, you can't say that! Maybe he just wants to understand golangthe syntax of templates so that he can develop Hugo theme, which is true.

For how to configure the golangrelevant moduleproperties, you can check the previous articles. This article will not go into details, but will focus on explaining html/templatethe syntax.

You can create a project by typing the following command in any empty file on your computer cmd(that is, the command line).

go mod init template.qiucode.cn #其中 template.qiucode.cn 是您项目模块名称,您可以起个响亮的名字,以便符合您的气质!(纯属笑谈)

Create a new file in the current directory main.goand type the following code:

package main

import (
"log"
"net/http"
)

func main() {

	mux := http.NewServeMux()
	mux.HandleFunc("/", home)
	mux.HandleFunc("/blog/view", snippetView)
	mux.HandleFunc("/blog/create", snippetCreate)
	log.Print("Starting server on :4000")
	err := http.ListenAndServe(":4000", mux)
	log.Fatal(err)

}

We piled up the original request processing method in main.gothe file and extracted it into a new file. Then you need to create a new handlers.gofile. As for the content, it is as follows:

package main

import (
	"fmt"
	"net/http"
	"strconv"
)

func home(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	w.Write([]byte("Hello from Snippetbox"))
}

func snippetView(w http.ResponseWriter, r *http.Request) {
	id, err := strconv.Atoi(r.URL.Query().Get("id"))
		if err != nil || id < 1 {
		http.NotFound(w, r)
		return
	}

	fmt.Fprintf(w, "Display a specific snippet with ID %d...", id)
}

func snippetCreate(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		w.Header().Set("Allow", http.MethodPost)
		http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
		return
	}
	w.Write([]byte("Create a new snippet..."))
}

template composition

Create a template file in the current folder home.tmpl, and the file path is as follows.

<!doctype html>
<html lang='zh'>
    <head>
        <meta charset='utf-8'>
        <title>首页</title>
    </head>
    <body>
        <header>
            <h1><a href='/'>这是头部</a></h1>
        </header>
        <main>
            <h2>主体部分s</h2>
            <p>写点什么吧!</p>
        </main>
        <footer>Powered by <a href='https://golang.org/'>Go</a></footer>
    </body>
</html>

Go back to handlers.gothe file and modify its homehandler function.

package main

import (
	"fmt"
	"html/template" // 新添加
    "log"           // 新添加
	"net/http"
	"strconv"
)

func home(w http.ResponseWriter, r *http.Request) {

	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	
	//解析模板文件
	ts, err := template.ParseFiles("./ui/html/pages/home.tmpl")
	if err != nil {
		log.Print(err.Error())
		http.Error(w, "Internal Server Error", 500)
		return
	}
	
	err = ts.Execute(w, nil)
	if err != nil {
		log.Print(err.Error())
		http.Error(w, "Internal Server Error", 500)
	}
}

//... 省略其他方法

It is true that there will be more *.tmplfiles in the folder, how to share the public content such as the header, sidebar, and bottom with other pages? In order to eliminate redundant content, all template files will include base.tmplfiles.

{
   
   {define "base"}}
<!doctype html>
<html lang='zh'>
    <head>
        <meta charset='utf-8'>
        <title>{
   
   {template "title" .}} - 秋码记录</title>
    </head>
    <body>
        <header>
            <h1><a href='/'>这是头部</a></h1>
        </header>
        <main>
            {
   
   {template "main" .}}
        </main>
        <footer>Powered by <a href='https://golang.org/'>Go</a></footer>
    </body>
</html>
{
   
   {end}}

{ {define "base"}}...{ {end}} Action to define a template named base, which contains the content we want to appear on each page. Internally, we use { {template "title" .}} the and operator to indicate that we want to call other named templates (called and ) { {template "main" .}} at specific locations .titlemain

Let's modify ui/html/pages/home.tmplthe contents of the file.

{
   
   {define "title"}}Home{
   
   {end}}
{
   
   {define "main"}}
    <h2>这是主体</h2>
    <p>说点什么吧!</p>
{
   
   {end}}

Of course, we have to modify the processing function handlers.goin home.

package main

import (
	"fmt"
	"html/template" // 新添加
    "log"           // 新添加
	"net/http"
	"strconv"
)

func home(w http.ResponseWriter, r *http.Request) {

	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	
	files := []string{
		"./ui/html/base.tmpl",
		"./ui/html/pages/home.tmpl",
	}
		
	ts, err := template.ParseFiles(files...)
	if err != nil {
		log.Print(err.Error())
		http.Error(w, "Internal Server Error", 500)
		return
	}

	
	err = ts.ExecuteTemplate(w, "base", nil)
	if err != nil {
		log.Print(err.Error())
		http.Error(w, "Internal Server Error", 500)
	}
		
}

//... 省略其他方法

So now, instead of directly containing HTML, our template set contains 3 named templates — base, , titleand main. We use ExecuteTemplate() methods to tell Gous exactly what basecontent we want to use in response (which in turn calls our titleand maintemplates).

template embedding

We want certain content to be abstracted and reused across different pages or layouts.

To illustrate this, let's create a navbar with the following sections.

{
   
   {define "nav"}}
    <nav>
        <a href='/'>首页</a>
    </nav>
{
   
   {end}}

At the same time, modify ui/html/base.tmplthe file.

{
   
   {define "base"}}
<!doctype html>
<html lang='zh'>
    <head>
        <meta charset='utf-8'>
        <title>{
   
   {template "title" .}} - 秋码记录</title>
    </head>
    <body>
        <header>
            <h1><a href='/'>这是头部</a></h1>
        </header>
        {
   
   {template "nav" .}}
        <main>
{
   
   {template "main" .}} {
   
   {/*添加了这一行内容*/}}
        </main>
        <footer>Powered by <a href='https://golang.org/'>Go</a></footer>
    </body>
</html>
{
   
   {end}}


Of course, the processing function handlers.goin the file homehas to be modified accordingly.

package main

import (
	"fmt"
	"html/template" // 新添加
    "log"           // 新添加
	"net/http"
	"strconv"
)

func home(w http.ResponseWriter, r *http.Request) {

	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	
	files := []string{
		"./ui/html/base.tmpl",
        "./ui/html/partials/nav.tmpl", //添加这一行内容
		"./ui/html/pages/home.tmpl",
	}
		
	ts, err := template.ParseFiles(files...)
	if err != nil {
		log.Print(err.Error())
		http.Error(w, "Internal Server Error", 500)
		return
	}

	
	err = ts.ExecuteTemplate(w, "base", nil)
	if err != nil {
		log.Print(err.Error())
		http.Error(w, "Internal Server Error", 500)
	}
		
}

//... 省略其他方法

block

As you also saw above, the { {template}}. In fact, golangwe also provide another, that is, Hugo·``中常用的{ {block}} ... { {end}}``` operation.

For example:

{
   
   {define "base"}}
    <h1>An example template</h1>
    {
   
   {block "sidebar" .}}
    	<p>My default sidebar content</p>
    {
   
   {end}}
{
   
   {end}}

You don't need { {block}}to include any default content and { {end}} actions in between. In this case, the called template is like "optional". If the template exists in the template set, it will be rendered. But if you don't, then nothing is displayed.

The author's small station: Qiuma record

Guess you like

Origin blog.csdn.net/coco2d_x2014/article/details/131622112