github.com/jgarto/itcv@v0.0.0-20180826224514-4eea09c1aa0d/examples/sites/present/dir.go (about) 1 // Copyright (c) 2018 Paul Jolly <paul@myitcv.org.uk>, all rights reserved. 2 // Use of this document is governed by a license found in the LICENSE document. 3 4 // This package contains a fair amount of copy-paste from 5 // https://godoc.org/golang.org/x/tools/cmd/present. The copyright notice from 6 // that repo can be seen below, and is linked 7 // https://github.com/golang/tools/blob/master/LICENSE 8 9 // Copyright 2012 The Go Authors. All rights reserved. 10 // Use of this source code is governed by a BSD-style 11 // license that can be found in the LICENSE file. 12 13 package main 14 15 import ( 16 "fmt" 17 "html/template" 18 "io" 19 "net/url" 20 "path" 21 "path/filepath" 22 23 "honnef.co/go/js/xhr" 24 25 "golang.org/x/tools/present" 26 ) 27 28 func isDoc(path string) bool { 29 _, ok := contentTemplate[filepath.Ext(path)] 30 return ok 31 } 32 33 var ( 34 // dirListTemplate holds the front page template. 35 dirListTemplate *template.Template 36 37 // contentTemplate maps the presentable file extensions to the 38 // template to be executed. 39 contentTemplate map[string]*template.Template 40 ) 41 42 func initTemplates(base string) error { 43 var err error 44 45 // Locate the template file. 46 actionTmplContents, err := Asset(filepath.Join(base, "templates/action.tmpl")) 47 if err != nil { 48 return err 49 } 50 51 contentTemplate = make(map[string]*template.Template) 52 53 for ext, contentTmpl := range map[string]string{ 54 ".slide": "slides.tmpl", 55 ".article": "article.tmpl", 56 } { 57 contentTmpl = filepath.Join(base, "templates", contentTmpl) 58 59 actionTmpl := present.Template() 60 actionTmpl = actionTmpl.Funcs(template.FuncMap{"playable": playable}) 61 actionTmpl, err = actionTmpl.Parse(string(actionTmplContents)) 62 if err != nil { 63 return err 64 } 65 66 contents, err := Asset(contentTmpl) 67 if err != nil { 68 return err 69 } 70 71 tmpl, err := actionTmpl.Parse(string(contents)) 72 if err != nil { 73 return err 74 } 75 contentTemplate[ext] = tmpl 76 77 } 78 79 return err 80 } 81 82 type xhrFileReader struct { 83 rootUrl *url.URL 84 } 85 86 func (x xhrFileReader) ReadFile(filename string) ([]byte, error) { 87 fmt.Printf("Read %v, %v\n", filename, x.rootUrl.String()) 88 v, err := url.Parse(filename) 89 if err != nil { 90 return nil, err 91 } 92 93 u := x.rootUrl.ResolveReference(v).String() 94 95 req := xhr.NewRequest("GET", u) 96 err = req.Send(nil) 97 if err != nil { 98 return nil, err 99 } 100 101 return []byte(req.ResponseText), nil 102 } 103 104 // renderDoc reads the present file, gets its template representation, 105 // and executes the template, sending output to w. 106 func renderDoc(w io.Writer, docUrl string, r io.Reader) error { 107 u, err := url.Parse(docUrl) 108 if err != nil { 109 return err 110 } 111 112 xhrRead := xhrFileReader{ 113 rootUrl: u, 114 } 115 116 ctxt := &present.Context{ 117 ReadFile: xhrRead.ReadFile, 118 } 119 120 docFile := path.Base(docUrl) 121 122 // Read the input and build the doc structure. 123 doc, err := ctxt.Parse(r, docFile, 0) 124 if err != nil { 125 return err 126 } 127 128 for _, s := range doc.Sections { 129 for i, e := range s.Elem { 130 switch v := e.(type) { 131 case present.Image: 132 vv, err := url.Parse(v.URL) 133 if err != nil { 134 panic(err) 135 } 136 137 v.URL = u.ResolveReference(vv).String() 138 s.Elem[i] = v 139 } 140 } 141 } 142 143 // Find which template should be executed. 144 tmpl := contentTemplate[filepath.Ext(docFile)] 145 146 mw := io.MultiWriter(w) 147 148 // Execute the template. 149 return doc.Render(mw, tmpl) 150 } 151 152 // showFile reports whether the given file should be displayed in the list. 153 func showFile(n string) bool { 154 switch filepath.Ext(n) { 155 case ".pdf": 156 case ".html": 157 case ".go": 158 default: 159 return isDoc(n) 160 } 161 return true 162 } 163 164 // showDir reports whether the given directory should be displayed in the list. 165 func showDir(n string) bool { 166 if len(n) > 0 && (n[0] == '.' || n[0] == '_') || n == "present" { 167 return false 168 } 169 return true 170 } 171 172 type dirListData struct { 173 Path string 174 Dirs, Slides, Articles, Other dirEntrySlice 175 } 176 177 type dirEntry struct { 178 Name, Path, Title string 179 } 180 181 type dirEntrySlice []dirEntry 182 183 func (s dirEntrySlice) Len() int { return len(s) } 184 func (s dirEntrySlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 185 func (s dirEntrySlice) Less(i, j int) bool { return s[i].Name < s[j].Name } 186 187 func playable(c present.Code) bool { 188 return present.PlayEnabled && c.Play && c.Ext == ".go" 189 }