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  }