|  | // Copyright 2012 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package template_test | 
|  |  | 
|  | import ( | 
|  | "io" | 
|  | "io/ioutil" | 
|  | "log" | 
|  | "os" | 
|  | "path/filepath" | 
|  | "text/template" | 
|  | ) | 
|  |  | 
|  | // templateFile defines the contents of a template to be stored in a file, for testing. | 
|  | type templateFile struct { | 
|  | name     string | 
|  | contents string | 
|  | } | 
|  |  | 
|  | func createTestDir(files []templateFile) string { | 
|  | dir, err := ioutil.TempDir("", "template") | 
|  | if err != nil { | 
|  | log.Fatal(err) | 
|  | } | 
|  | for _, file := range files { | 
|  | f, err := os.Create(filepath.Join(dir, file.name)) | 
|  | if err != nil { | 
|  | log.Fatal(err) | 
|  | } | 
|  | defer f.Close() | 
|  | _, err = io.WriteString(f, file.contents) | 
|  | if err != nil { | 
|  | log.Fatal(err) | 
|  | } | 
|  | } | 
|  | return dir | 
|  | } | 
|  |  | 
|  | // Here we demonstrate loading a set of templates from a directory. | 
|  | func ExampleTemplate_glob() { | 
|  | // Here we create a temporary directory and populate it with our sample | 
|  | // template definition files; usually the template files would already | 
|  | // exist in some location known to the program. | 
|  | dir := createTestDir([]templateFile{ | 
|  | // T0.tmpl is a plain template file that just invokes T1. | 
|  | {"T0.tmpl", `T0 invokes T1: ({{template "T1"}})`}, | 
|  | // T1.tmpl defines a template, T1 that invokes T2. | 
|  | {"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`}, | 
|  | // T2.tmpl defines a template T2. | 
|  | {"T2.tmpl", `{{define "T2"}}This is T2{{end}}`}, | 
|  | }) | 
|  | // Clean up after the test; another quirk of running as an example. | 
|  | defer os.RemoveAll(dir) | 
|  |  | 
|  | // pattern is the glob pattern used to find all the template files. | 
|  | pattern := filepath.Join(dir, "*.tmpl") | 
|  |  | 
|  | // Here starts the example proper. | 
|  | // T0.tmpl is the first name matched, so it becomes the starting template, | 
|  | // the value returned by ParseGlob. | 
|  | tmpl := template.Must(template.ParseGlob(pattern)) | 
|  |  | 
|  | err := tmpl.Execute(os.Stdout, nil) | 
|  | if err != nil { | 
|  | log.Fatalf("template execution: %s", err) | 
|  | } | 
|  | // Output: | 
|  | // T0 invokes T1: (T1 invokes T2: (This is T2)) | 
|  | } | 
|  |  | 
|  | // This example demonstrates one way to share some templates | 
|  | // and use them in different contexts. In this variant we add multiple driver | 
|  | // templates by hand to an existing bundle of templates. | 
|  | func ExampleTemplate_helpers() { | 
|  | // Here we create a temporary directory and populate it with our sample | 
|  | // template definition files; usually the template files would already | 
|  | // exist in some location known to the program. | 
|  | dir := createTestDir([]templateFile{ | 
|  | // T1.tmpl defines a template, T1 that invokes T2. | 
|  | {"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`}, | 
|  | // T2.tmpl defines a template T2. | 
|  | {"T2.tmpl", `{{define "T2"}}This is T2{{end}}`}, | 
|  | }) | 
|  | // Clean up after the test; another quirk of running as an example. | 
|  | defer os.RemoveAll(dir) | 
|  |  | 
|  | // pattern is the glob pattern used to find all the template files. | 
|  | pattern := filepath.Join(dir, "*.tmpl") | 
|  |  | 
|  | // Here starts the example proper. | 
|  | // Load the helpers. | 
|  | templates := template.Must(template.ParseGlob(pattern)) | 
|  | // Add one driver template to the bunch; we do this with an explicit template definition. | 
|  | _, err := templates.Parse("{{define `driver1`}}Driver 1 calls T1: ({{template `T1`}})\n{{end}}") | 
|  | if err != nil { | 
|  | log.Fatal("parsing driver1: ", err) | 
|  | } | 
|  | // Add another driver template. | 
|  | _, err = templates.Parse("{{define `driver2`}}Driver 2 calls T2: ({{template `T2`}})\n{{end}}") | 
|  | if err != nil { | 
|  | log.Fatal("parsing driver2: ", err) | 
|  | } | 
|  | // We load all the templates before execution. This package does not require | 
|  | // that behavior but html/template's escaping does, so it's a good habit. | 
|  | err = templates.ExecuteTemplate(os.Stdout, "driver1", nil) | 
|  | if err != nil { | 
|  | log.Fatalf("driver1 execution: %s", err) | 
|  | } | 
|  | err = templates.ExecuteTemplate(os.Stdout, "driver2", nil) | 
|  | if err != nil { | 
|  | log.Fatalf("driver2 execution: %s", err) | 
|  | } | 
|  | // Output: | 
|  | // Driver 1 calls T1: (T1 invokes T2: (This is T2)) | 
|  | // Driver 2 calls T2: (This is T2) | 
|  | } | 
|  |  | 
|  | // This example demonstrates how to use one group of driver | 
|  | // templates with distinct sets of helper templates. | 
|  | func ExampleTemplate_share() { | 
|  | // Here we create a temporary directory and populate it with our sample | 
|  | // template definition files; usually the template files would already | 
|  | // exist in some location known to the program. | 
|  | dir := createTestDir([]templateFile{ | 
|  | // T0.tmpl is a plain template file that just invokes T1. | 
|  | {"T0.tmpl", "T0 ({{.}} version) invokes T1: ({{template `T1`}})\n"}, | 
|  | // T1.tmpl defines a template, T1 that invokes T2. Note T2 is not defined | 
|  | {"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`}, | 
|  | }) | 
|  | // Clean up after the test; another quirk of running as an example. | 
|  | defer os.RemoveAll(dir) | 
|  |  | 
|  | // pattern is the glob pattern used to find all the template files. | 
|  | pattern := filepath.Join(dir, "*.tmpl") | 
|  |  | 
|  | // Here starts the example proper. | 
|  | // Load the drivers. | 
|  | drivers := template.Must(template.ParseGlob(pattern)) | 
|  |  | 
|  | // We must define an implementation of the T2 template. First we clone | 
|  | // the drivers, then add a definition of T2 to the template name space. | 
|  |  | 
|  | // 1. Clone the helper set to create a new name space from which to run them. | 
|  | first, err := drivers.Clone() | 
|  | if err != nil { | 
|  | log.Fatal("cloning helpers: ", err) | 
|  | } | 
|  | // 2. Define T2, version A, and parse it. | 
|  | _, err = first.Parse("{{define `T2`}}T2, version A{{end}}") | 
|  | if err != nil { | 
|  | log.Fatal("parsing T2: ", err) | 
|  | } | 
|  |  | 
|  | // Now repeat the whole thing, using a different version of T2. | 
|  | // 1. Clone the drivers. | 
|  | second, err := drivers.Clone() | 
|  | if err != nil { | 
|  | log.Fatal("cloning drivers: ", err) | 
|  | } | 
|  | // 2. Define T2, version B, and parse it. | 
|  | _, err = second.Parse("{{define `T2`}}T2, version B{{end}}") | 
|  | if err != nil { | 
|  | log.Fatal("parsing T2: ", err) | 
|  | } | 
|  |  | 
|  | // Execute the templates in the reverse order to verify the | 
|  | // first is unaffected by the second. | 
|  | err = second.ExecuteTemplate(os.Stdout, "T0.tmpl", "second") | 
|  | if err != nil { | 
|  | log.Fatalf("second execution: %s", err) | 
|  | } | 
|  | err = first.ExecuteTemplate(os.Stdout, "T0.tmpl", "first") | 
|  | if err != nil { | 
|  | log.Fatalf("first: execution: %s", err) | 
|  | } | 
|  |  | 
|  | // Output: | 
|  | // T0 (second version) invokes T1: (T1 invokes T2: (T2, version B)) | 
|  | // T0 (first version) invokes T1: (T1 invokes T2: (T2, version A)) | 
|  | } |