github.com/kovansky/hugo@v0.92.3-0.20220224232819-63076e4ff19f/tpl/internal/go_templates/texttemplate/examplefiles_test.go (about)

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