// Copyright 2013 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. //modify 2013-2014 visualfc package gopresent import ( "fmt" "html/template" "io" "os" "path/filepath" "github.com/visualfc/gotools/command" "golang.org/x/tools/present" ) var Command = &command.Command{ Run: runPresent, UsageLine: "gopresent", Short: "golang present util", Long: `golang present util`, } var presentVerifyOnly bool var presentInput string var presentStdout bool var presentOutput string func init() { Command.Flag.BoolVar(&presentVerifyOnly, "v", false, "verify present only") Command.Flag.BoolVar(&presentStdout, "stdout", false, "output use std output") Command.Flag.StringVar(&presentInput, "i", "", "input golang present file") Command.Flag.StringVar(&presentOutput, "o", "", "output html file name") } func runPresent(cmd *command.Command, args []string) error { if presentInput == "" || !isDoc(presentInput) { cmd.Usage() return os.ErrInvalid } if presentVerifyOnly { err := VerifyDoc(presentInput) if err != nil { fmt.Fprintf(os.Stderr, "present:%s", err) command.SetExitStatus(3) command.Exit() } return nil } w := os.Stdout if !presentStdout { if presentOutput == "" { presentOutput = presentInput + ".html" } ext := filepath.Ext(presentOutput) if ext != ".htm" && ext != ".html" { presentOutput += ".html" } var err error w, err = os.Create(presentOutput) if err != nil { fmt.Fprintf(os.Stderr, "present:%s", err) command.SetExitStatus(3) command.Exit() } } err := RenderDoc(w, presentInput) if err != nil { fmt.Fprintf(os.Stderr, "present:%s", err) command.SetExitStatus(3) command.Exit() } return nil } var extensions = map[string]string{ ".slide": "slides.tmpl", ".article": "article.tmpl", } var extensions_tmpl = map[string]string{ ".slide": slides_tmpl, ".article": article_tmpl, } func isDoc(path string) bool { _, ok := extensions[filepath.Ext(path)] return ok } func VerifyDoc(docFile string) error { doc, err := parse(docFile, 0) if err != nil { return err } dir := filepath.Dir(docFile) return verify_doc(dir, doc) } // renderDoc reads the present file, builds its template representation, // and executes the template, sending output to w. func renderDoc(w io.Writer, base, docFile string) error { // Read the input and build the doc structure. doc, err := parse(docFile, 0) if err != nil { return err } // Find which template should be executed. ext := filepath.Ext(docFile) contentTmpl, ok := extensions[ext] if !ok { return fmt.Errorf("no template for extension %v", ext) } // Locate the template file. actionTmpl := filepath.Join(base, "templates/action.tmpl") contentTmpl = filepath.Join(base, "templates", contentTmpl) // Read and parse the input. tmpl := present.Template() tmpl = tmpl.Funcs(template.FuncMap{"playable": playable}) if _, err := tmpl.ParseFiles(actionTmpl, contentTmpl); err != nil { return err } // Execute the template. return doc.Render(w, tmpl) } func RenderDoc(w io.Writer, docFile string) error { // Read the input and build the doc structure. doc, err := parse(docFile, 0) if err != nil { return err } // Find which template should be executed. ext := filepath.Ext(docFile) contentTmpl, ok := extensions_tmpl[ext] if !ok { return fmt.Errorf("no template for extension %v", ext) } // Locate the template file. actionTmpl := action_tmpl //filepath.Join(base, "templates/action.tmpl") // Read and parse the input. tmpl := present.Template() tmpl = tmpl.Funcs(template.FuncMap{"playable": playable}) if tmpl, err = tmpl.New("action").Parse(actionTmpl); err != nil { return err } if tmpl, err = tmpl.New("content").Parse(contentTmpl); err != nil { return err } // Execute the template. return doc.Render(w, tmpl) } 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 playable(c present.Code) bool { return present.PlayEnabled && c.Play } func isSkipURL(url string) bool { if filepath.HasPrefix(url, "http://") { return true } if filepath.HasPrefix(url, "https://") { return true } return false } func verify_path(root string, url string) error { if isSkipURL(url) { return nil } path := url if !filepath.IsAbs(url) { path = filepath.Join(root, path) } _, err := os.Stat(path) if err != nil { return err } return nil } func verify_doc(root string, doc *present.Doc) error { for _, section := range doc.Sections { for _, elem := range section.Elem { switch i := elem.(type) { case present.Image: if err := verify_path(root, i.URL); err != nil { return fmt.Errorf("! .image %s not exist", i.URL) } } } } return nil } var action_tmpl = ` {/* This is the action template. It determines how the formatting actions are rendered. */} {{define "section"}} {{.FormattedNumber}} {{.Title}} {{range .Elem}}{{elem $.Template .}}{{end}} {{end}} {{define "list"}} {{end}} {{define "text"}} {{if .Pre}}
{{range .Lines}}{{.}}{{end}}
{{else}}

{{range $i, $l := .Lines}}{{if $i}}{{template "newline"}} {{end}}{{style $l}}{{end}}

{{end}} {{end}} {{define "code"}}
{{.Text}}
{{end}} {{define "image"}}
{{end}} {{define "iframe"}} {{end}} {{define "link"}}{{end}} {{define "html"}}{{.HTML}}{{end}} ` var article_tmpl = ` {/* This is the article template. It defines how articles are formatted. */} {{define "root"}} {{.Title}}
{{.Title}} {{with .Subtitle}}{{.}}{{end}}
{{with .Sections}}
{{template "TOC" .}}
{{end}} {{range .Sections}} {{elem $.Template .}} {{end}}{{/* of Section block */}}

Authors

{{range .Authors}}
{{range .Elem}}{{elem $.Template .}}{{end}}
{{end}}
{{end}} {{define "TOC"}} {{end}} {{define "newline"}} {{/* No automatic line break. Paragraphs are free-form. */}} {{end}} ` var slides_tmpl = ` {/* This is the slide template. It defines how presentations are formatted. */} {{define "root"}} {{.Title}}

{{.Title}}

{{with .Subtitle}}

{{.}}

{{end}} {{if not .Time.IsZero}}

{{.Time.Format "2 January 2006"}}

{{end}} {{range .Authors}}
{{range .TextElem}}{{elem $.Template .}}{{end}}
{{end}}
{{range $i, $s := .Sections}}
{{if $s.Elem}}

{{$s.Title}}

{{range $s.Elem}}{{elem $.Template .}}{{end}} {{else}}

{{$s.Title}}

{{end}}
{{end}}{{/* of Slide block */}}

Thank you

{{range .Authors}}
{{range .Elem}}{{elem $.Template .}}{{end}}
{{end}}
{{if .PlayEnabled}} {{end}} {{end}} {{define "newline"}}
{{end}} `