hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

examplefiles_test.go (7726B)

    1 // Copyright 2016 The Go Authors. All rights reserved.
    2 // Use of this source code is governed by a BSD-style
    3 // license that can be found in the LICENSE file.
    4 
    5 //go:build go1.13
    6 // +build go1.13
    7 
    8 package template_test
    9 
   10 import (
   11 	"io"
   12 	"log"
   13 	"os"
   14 	"path/filepath"
   15 
   16 	template "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate"
   17 )
   18 
   19 // templateFile defines the contents of a template to be stored in a file, for testing.
   20 type templateFile struct {
   21 	name     string
   22 	contents string
   23 }
   24 
   25 func createTestDir(files []templateFile) string {
   26 	dir, err := os.MkdirTemp("", "template")
   27 	if err != nil {
   28 		log.Fatal(err)
   29 	}
   30 	for _, file := range files {
   31 		f, err := os.Create(filepath.Join(dir, file.name))
   32 		if err != nil {
   33 			log.Fatal(err)
   34 		}
   35 		defer f.Close()
   36 		_, err = io.WriteString(f, file.contents)
   37 		if err != nil {
   38 			log.Fatal(err)
   39 		}
   40 	}
   41 	return dir
   42 }
   43 
   44 // The following example is duplicated in text/template; keep them in sync.
   45 
   46 // Here we demonstrate loading a set of templates from a directory.
   47 func ExampleTemplate_glob() {
   48 	// Here we create a temporary directory and populate it with our sample
   49 	// template definition files; usually the template files would already
   50 	// exist in some location known to the program.
   51 	dir := createTestDir([]templateFile{
   52 		// T0.tmpl is a plain template file that just invokes T1.
   53 		{"T0.tmpl", `T0 invokes T1: ({{template "T1"}})`},
   54 		// T1.tmpl defines a template, T1 that invokes T2.
   55 		{"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`},
   56 		// T2.tmpl defines a template T2.
   57 		{"T2.tmpl", `{{define "T2"}}This is T2{{end}}`},
   58 	})
   59 	// Clean up after the test; another quirk of running as an example.
   60 	defer os.RemoveAll(dir)
   61 
   62 	// pattern is the glob pattern used to find all the template files.
   63 	pattern := filepath.Join(dir, "*.tmpl")
   64 
   65 	// Here starts the example proper.
   66 	// T0.tmpl is the first name matched, so it becomes the starting template,
   67 	// the value returned by ParseGlob.
   68 	tmpl := template.Must(template.ParseGlob(pattern))
   69 
   70 	err := tmpl.Execute(os.Stdout, nil)
   71 	if err != nil {
   72 		log.Fatalf("template execution: %s", err)
   73 	}
   74 	// Output:
   75 	// T0 invokes T1: (T1 invokes T2: (This is T2))
   76 }
   77 
   78 // Here we demonstrate loading a set of templates from files in different directories
   79 func ExampleTemplate_parsefiles() {
   80 	// Here we create different temporary directories and populate them with our sample
   81 	// template definition files; usually the template files would already
   82 	// exist in some location known to the program.
   83 	dir1 := createTestDir([]templateFile{
   84 		// T1.tmpl is a plain template file that just invokes T2.
   85 		{"T1.tmpl", `T1 invokes T2: ({{template "T2"}})`},
   86 	})
   87 
   88 	dir2 := createTestDir([]templateFile{
   89 		// T2.tmpl defines a template T2.
   90 		{"T2.tmpl", `{{define "T2"}}This is T2{{end}}`},
   91 	})
   92 
   93 	// Clean up after the test; another quirk of running as an example.
   94 	defer func(dirs ...string) {
   95 		for _, dir := range dirs {
   96 			os.RemoveAll(dir)
   97 		}
   98 	}(dir1, dir2)
   99 
  100 	// Here starts the example proper.
  101 	// Let's just parse only dir1/T0 and dir2/T2
  102 	paths := []string{
  103 		filepath.Join(dir1, "T1.tmpl"),
  104 		filepath.Join(dir2, "T2.tmpl"),
  105 	}
  106 	tmpl := template.Must(template.ParseFiles(paths...))
  107 
  108 	err := tmpl.Execute(os.Stdout, nil)
  109 	if err != nil {
  110 		log.Fatalf("template execution: %s", err)
  111 	}
  112 	// Output:
  113 	// T1 invokes T2: (This is T2)
  114 }
  115 
  116 // The following example is duplicated in text/template; keep them in sync.
  117 
  118 // This example demonstrates one way to share some templates
  119 // and use them in different contexts. In this variant we add multiple driver
  120 // templates by hand to an existing bundle of templates.
  121 func ExampleTemplate_helpers() {
  122 	// Here we create a temporary directory and populate it with our sample
  123 	// template definition files; usually the template files would already
  124 	// exist in some location known to the program.
  125 	dir := createTestDir([]templateFile{
  126 		// T1.tmpl defines a template, T1 that invokes T2.
  127 		{"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`},
  128 		// T2.tmpl defines a template T2.
  129 		{"T2.tmpl", `{{define "T2"}}This is T2{{end}}`},
  130 	})
  131 	// Clean up after the test; another quirk of running as an example.
  132 	defer os.RemoveAll(dir)
  133 
  134 	// pattern is the glob pattern used to find all the template files.
  135 	pattern := filepath.Join(dir, "*.tmpl")
  136 
  137 	// Here starts the example proper.
  138 	// Load the helpers.
  139 	templates := template.Must(template.ParseGlob(pattern))
  140 	// Add one driver template to the bunch; we do this with an explicit template definition.
  141 	_, err := templates.Parse("{{define `driver1`}}Driver 1 calls T1: ({{template `T1`}})\n{{end}}")
  142 	if err != nil {
  143 		log.Fatal("parsing driver1: ", err)
  144 	}
  145 	// Add another driver template.
  146 	_, err = templates.Parse("{{define `driver2`}}Driver 2 calls T2: ({{template `T2`}})\n{{end}}")
  147 	if err != nil {
  148 		log.Fatal("parsing driver2: ", err)
  149 	}
  150 	// We load all the templates before execution. This package does not require
  151 	// that behavior but html/template's escaping does, so it's a good habit.
  152 	err = templates.ExecuteTemplate(os.Stdout, "driver1", nil)
  153 	if err != nil {
  154 		log.Fatalf("driver1 execution: %s", err)
  155 	}
  156 	err = templates.ExecuteTemplate(os.Stdout, "driver2", nil)
  157 	if err != nil {
  158 		log.Fatalf("driver2 execution: %s", err)
  159 	}
  160 	// Output:
  161 	// Driver 1 calls T1: (T1 invokes T2: (This is T2))
  162 	// Driver 2 calls T2: (This is T2)
  163 }
  164 
  165 // The following example is duplicated in text/template; keep them in sync.
  166 
  167 // This example demonstrates how to use one group of driver
  168 // templates with distinct sets of helper templates.
  169 func ExampleTemplate_share() {
  170 	// Here we create a temporary directory and populate it with our sample
  171 	// template definition files; usually the template files would already
  172 	// exist in some location known to the program.
  173 	dir := createTestDir([]templateFile{
  174 		// T0.tmpl is a plain template file that just invokes T1.
  175 		{"T0.tmpl", "T0 ({{.}} version) invokes T1: ({{template `T1`}})\n"},
  176 		// T1.tmpl defines a template, T1 that invokes T2. Note T2 is not defined
  177 		{"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`},
  178 	})
  179 	// Clean up after the test; another quirk of running as an example.
  180 	defer os.RemoveAll(dir)
  181 
  182 	// pattern is the glob pattern used to find all the template files.
  183 	pattern := filepath.Join(dir, "*.tmpl")
  184 
  185 	// Here starts the example proper.
  186 	// Load the drivers.
  187 	drivers := template.Must(template.ParseGlob(pattern))
  188 
  189 	// We must define an implementation of the T2 template. First we clone
  190 	// the drivers, then add a definition of T2 to the template name space.
  191 
  192 	// 1. Clone the helper set to create a new name space from which to run them.
  193 	first, err := drivers.Clone()
  194 	if err != nil {
  195 		log.Fatal("cloning helpers: ", err)
  196 	}
  197 	// 2. Define T2, version A, and parse it.
  198 	_, err = first.Parse("{{define `T2`}}T2, version A{{end}}")
  199 	if err != nil {
  200 		log.Fatal("parsing T2: ", err)
  201 	}
  202 
  203 	// Now repeat the whole thing, using a different version of T2.
  204 	// 1. Clone the drivers.
  205 	second, err := drivers.Clone()
  206 	if err != nil {
  207 		log.Fatal("cloning drivers: ", err)
  208 	}
  209 	// 2. Define T2, version B, and parse it.
  210 	_, err = second.Parse("{{define `T2`}}T2, version B{{end}}")
  211 	if err != nil {
  212 		log.Fatal("parsing T2: ", err)
  213 	}
  214 
  215 	// Execute the templates in the reverse order to verify the
  216 	// first is unaffected by the second.
  217 	err = second.ExecuteTemplate(os.Stdout, "T0.tmpl", "second")
  218 	if err != nil {
  219 		log.Fatalf("second execution: %s", err)
  220 	}
  221 	err = first.ExecuteTemplate(os.Stdout, "T0.tmpl", "first")
  222 	if err != nil {
  223 		log.Fatalf("first: execution: %s", err)
  224 	}
  225 
  226 	// Output:
  227 	// T0 (second version) invokes T1: (T1 invokes T2: (T2, version B))
  228 	// T0 (first version) invokes T1: (T1 invokes T2: (T2, version A))
  229 }