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