template: add example to demonstrate template blocks
Fixes golang/go#14285
Change-Id: I3b32b7fc19960a77778e84cba2a0a95b49dbdf16
Reviewed-on: https://go-review.googlesource.com/19443
Reviewed-by: Rob Pike <r@golang.org>
Reviewed-by: Chris Broadfoot <cbro@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
diff --git a/README.md b/README.md
index aeb8c6f..da31aaf 100644
--- a/README.md
+++ b/README.md
@@ -50,3 +50,8 @@
starting point for your own code.
_Note_: The `goapp` tool is part of the [Google App Engine SDK for Go](https://cloud.google.com/appengine/downloads#Google_App_Engine_SDK_for_Go).
+
+### [template][template/] ([godoc](//godoc.org/github.com/golang/example/template))
+
+A trivial web server that demonstrates the use of the
+[`template` package](https://golang.org/pkg/text/template/)'s `block` feature.
diff --git a/template/image.tmpl b/template/image.tmpl
new file mode 100644
index 0000000..14d1097
--- /dev/null
+++ b/template/image.tmpl
@@ -0,0 +1,9 @@
+{{define "content"}}
+<div id="image">
+ <img src="{{.URL}}" title="{{.Title}}" alt="{{.Title}}">
+</div>
+{{end}}
+
+{{define "sidebar"}}
+<a href="/">Back</a>
+{{end}}
diff --git a/template/index.tmpl b/template/index.tmpl
new file mode 100644
index 0000000..9b77440
--- /dev/null
+++ b/template/index.tmpl
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>{{.Title}}</title>
+ <style>
+ body {
+ font-family: sans-serif;
+ }
+ h1 {
+ background: #ddd;
+ }
+ #sidebar {
+ float: right;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>{{.Title}}</h1>
+
+ <div id="sidebar">
+ {{block "sidebar" .}}
+ <h2>Links</h2>
+ {{/* The dashes in the following template directives
+ ensure the generated HTML of this list contains no
+ extraneous spaces or line breaks. */}}
+ <ul id="sidebar">
+ {{- range .Links}}
+ <li><a href="{{.URL}}">{{.Title}}</a></li>
+ {{- end}}
+ </ul>
+ {{end}}
+ </div>
+
+ {{block "content" .}}
+ <div id="content">
+ {{.Body}}
+ </div>
+ {{end}}
+ </body>
+</html>
diff --git a/template/main.go b/template/main.go
new file mode 100644
index 0000000..5da5475
--- /dev/null
+++ b/template/main.go
@@ -0,0 +1,97 @@
+/*
+Copyright 2016 Google Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Command template is a trivial web server that uses the text/template (and
+// html/template) package's "block" feature to implement a kind of template
+// inheritance.
+//
+// It should be executed from the directory in which the source resides,
+// as it will look for its template files in the current directory.
+package main
+
+import (
+ "html/template"
+ "log"
+ "net/http"
+ "strings"
+)
+
+func main() {
+ http.HandleFunc("/", indexHandler)
+ http.HandleFunc("/image/", imageHandler)
+ log.Fatal(http.ListenAndServe("localhost:8080", nil))
+}
+
+// indexTemplate is the main site template.
+// The default template includes two template blocks ("sidebar" and "content")
+// that may be replaced in templates derived from this one.
+var indexTemplate = template.Must(template.ParseFiles("index.tmpl"))
+
+// Index is a data structure used to populate an indexTemplate.
+type Index struct {
+ Title string
+ Body string
+ Links []Link
+}
+
+type Link struct {
+ URL, Title string
+}
+
+// indexHandler is an HTTP handler that serves the index page.
+func indexHandler(w http.ResponseWriter, r *http.Request) {
+ data := &Index{
+ Title: "Image gallery",
+ Body: "Welcome to the image gallery.",
+ }
+ for name, img := range images {
+ data.Links = append(data.Links, Link{
+ URL: "/image/" + name,
+ Title: img.Title,
+ })
+ }
+ if err := indexTemplate.Execute(w, data); err != nil {
+ log.Println(err)
+ }
+}
+
+// imageTemplate is a clone of indexTemplate that provides
+// alternate "sidebar" and "content" templates.
+var imageTemplate = template.Must(template.Must(indexTemplate.Clone()).ParseFiles("image.tmpl"))
+
+// Image is a data structure used to populate an imageTemplate.
+type Image struct {
+ Title string
+ URL string
+}
+
+// imageHandler is an HTTP handler that serves the image pages.
+func imageHandler(w http.ResponseWriter, r *http.Request) {
+ data, ok := images[strings.TrimPrefix(r.URL.Path, "/image/")]
+ if !ok {
+ http.NotFound(w, r)
+ return
+ }
+ if err := imageTemplate.Execute(w, data); err != nil {
+ log.Println(err)
+ }
+}
+
+// images specifies the site content: a collection of images.
+var images = map[string]*Image{
+ "go": {"The Go Gopher", "https://golang.org/doc/gopher/frontpage.png"},
+ "google": {"The Google Logo", "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"},
+}