func parse(name string, mode present.ParseMode) (*present.Doc, error) { f, err := os.Open(name) if err != nil { return nil, err } defer f.Close() return present.Parse(f, name, 0) }
func presentSlide(w http.ResponseWriter, r *http.Request) { slideIdParam := strings.SplitN(r.URL.Path, "/", 2)[1] slideId := index.getSlideId(slideIdParam) if slideId == "" { http.NotFound(w, r) return } slideFile := filepath.Join(*slidesDir, slideId, "main.slide") f, err := os.Open(slideFile) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } doc, err := present.Parse(f, slideFile, 0) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } tmpl := present.Template() tmpl.Funcs(template.FuncMap{"playable": func(c present.Code) bool { return false }, "rSlideId": func() string { return slideIdParam }, "userRole": func() string { if slideId == slideIdParam { return "p" } else { return "v" } }}) _, err = tmpl.New("action").Parse(actionTmpl) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } _, err = tmpl.New("slides").Parse(slidesTmpl) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } if err := doc.Render(w, tmpl); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } }
func loadHomeArticle() []byte { const fname = "assets/home.article" f, err := os.Open(fname) if err != nil { panic(err) } defer f.Close() doc, err := present.Parse(f, fname, 0) if err != nil { panic(err) } var buf bytes.Buffer if err := renderPresentation(&buf, fname, doc); err != nil { panic(err) } return buf.Bytes() }
// parseLesson parses and returns a lesson content given its name and // the template to render it. func parseLesson(tmpl *template.Template, path string) ([]byte, error) { f, err := os.Open(path) if err != nil { return nil, err } defer f.Close() doc, err := present.Parse(prepContent(f), path, 0) if err != nil { return nil, err } lesson := Lesson{ doc.Title, doc.Subtitle, make([]Page, len(doc.Sections)), } for i, sec := range doc.Sections { p := &lesson.Pages[i] w := new(bytes.Buffer) if err := sec.Render(w, tmpl); err != nil { return nil, fmt.Errorf("render section: %v", err) } p.Title = sec.Title p.Content = w.String() codes := findPlayCode(sec) p.Files = make([]File, len(codes)) for i, c := range codes { f := &p.Files[i] f.Name = c.FileName f.Content = string(c.Raw) } } w := new(bytes.Buffer) if err := json.NewEncoder(w).Encode(lesson); err != nil { return nil, fmt.Errorf("encode lesson: %v", err) } return w.Bytes(), nil }
// initTour loads tour.article and the relevant HTML templates from the given // tour root, and renders the template to the tourContent global variable. func initTour(root string) error { // Make sure playground is enabled before rendering. present.PlayEnabled = true // Open and parse source file. source := *article f, err := os.Open(source) if err != nil { // See if it exists in the content directory in the root. source = filepath.Join(root, "content", source) f, err = os.Open(source) if err != nil { return err } } defer f.Close() doc, err := present.Parse(prepContent(f), source, 0) if err != nil { return err } // Set up templates. action := filepath.Join(root, "template", "action.tmpl") tour := filepath.Join(root, "template", "tour.tmpl") t := present.Template().Funcs(template.FuncMap{"nocode": nocode, "socketAddr": socketAddr}) _, err = t.ParseFiles(action, tour) if err != nil { return err } // Render. buf := new(bytes.Buffer) if err := doc.Render(buf, t); err != nil { return err } tourContent = buf.Bytes() return nil }
// loadDocs reads all content from the provided file system root, renders all // the articles it finds, adds them to the Server's docs field, computes the // denormalized docPaths, docTags, and tags fields, and populates the various // helper fields (Next, Previous, Related) for each Doc. func (s *Server) loadDocs(root string) error { s.docs = s.docs[:0] // Read content into docs field. const ext = ".article" fn := func(p string, info os.FileInfo, err error) error { if filepath.Ext(p) != ext { return nil } f, err := os.Open(p) if err != nil { return err } defer f.Close() d, err := present.Parse(f, p, 0) if err != nil { return err } html := new(bytes.Buffer) err = d.Render(html, s.template.doc) if err != nil { return err } p = p[len(root) : len(p)-len(ext)] // trim root and extension p = filepath.ToSlash(p) s.docs = append(s.docs, &Doc{ Doc: d, Path: p, Permalink: baseURL + p, HTML: template.HTML(html.String()), }) return nil } err := filepath.Walk(root, fn) if err != nil { return err } sort.Sort(docsByTime(s.docs)) // Pull out doc paths and tags and put in reverse-associating maps. s.docPaths = make(map[string]*Doc) s.docTags = make(map[string][]*Doc) for _, d := range s.docs { s.docPaths[d.Path] = d for _, t := range d.Tags { s.docTags[t] = append(s.docTags[t], d) } } // Pull out unique sorted list of tags. for t := range s.docTags { s.tags = append(s.tags, t) } sort.Strings(s.tags) // Set up presentation-related fields, Newer, Older, and Related. for _, doc := range s.docs { // Newer, Older: docs adjacent to doc for i := range s.docs { if s.docs[i] != doc { continue } if i > 0 { doc.Newer = s.docs[i-1] } if i+1 < len(s.docs) { doc.Older = s.docs[i+1] } break } // Related: all docs that share tags with doc. related := make(map[*Doc]bool) for _, t := range doc.Tags { for _, d := range s.docTags[t] { if d != doc { related[d] = true } } } for d := range related { doc.Related = append(doc.Related, d) } sort.Sort(docsByTime(doc.Related)) } return nil }