go.talks/present: give presenter fields a more free format
R=r
CC=gobot, golang-dev
https://golang.org/cl/6674051
diff --git a/present/doc.go b/present/doc.go
index f3d9aca..4f368d7 100644
--- a/present/doc.go
+++ b/present/doc.go
@@ -29,9 +29,12 @@
<blank line>
Presenter Name
Job title, Company
- Google+ profile link
- @twitter_name
+ joe@example.com
http://url/
+ @twitter_name
+
+The presenter section may contain a mixture of text, twitter names, and links.
+Only the plain text lines will be displayed on the presentation front page.
Multiple presenters may be specified, separated by a blank line.
diff --git a/present/link.go b/present/link.go
index 7fccab5..e5c685a 100644
--- a/present/link.go
+++ b/present/link.go
@@ -38,7 +38,11 @@
label := ""
switch len(arg) {
case 0:
- label = strings.Replace(url.String(), url.Scheme+"://", "", 1)
+ scheme := url.Scheme + "://"
+ if url.Scheme == "mailto" {
+ scheme = "mailto:"
+ }
+ label = strings.Replace(url.String(), scheme, "", 1)
default:
label = strings.Join(arg, " ")
}
diff --git a/present/parse.go b/present/parse.go
index 26d7d0e..108b9b1 100644
--- a/present/parse.go
+++ b/present/parse.go
@@ -11,6 +11,8 @@
"fmt"
"html/template"
"io"
+ "log"
+ "net/url"
"path/filepath"
"strings"
"unicode"
@@ -75,11 +77,20 @@
// Presenter represents the person who wrote and/or is giving the presentation.
type Presenter struct {
- Name string `json:"name"`
- Company string `json:"company"`
- Gplus string `json:"gplus"`
- Twitter string `json:"twitter"`
- WWW string `json:"www"`
+ Elem []Elem
+}
+
+// TextElem returns the first text elements of the presenter details.
+// This is used to display the presenters' name, job title, and company
+// without the contact details.
+func (p *Presenter) TextElem() (elems []Elem) {
+ for _, el := range p.Elem {
+ if _, ok := el.(Text); !ok {
+ break
+ }
+ elems = append(elems, el)
+ }
+ return
}
// Slide represents a single presentation slide.
@@ -201,35 +212,7 @@
return pres, nil
}
// Presenters
- for {
- var text string
- text, ok = lines.nextNonEmpty()
- if !ok {
- return nil, errors.New("unexpected EOF")
- }
- if strings.HasPrefix(text, "* ") {
- lines.back()
- break
- }
- p := Presenter{Name: text}
- p.Company, ok = lines.next()
- if !ok {
- return nil, errors.New("no company")
- }
- p.Gplus, ok = lines.next()
- if !ok {
- return nil, errors.New("no google+ link")
- }
- p.Twitter, ok = lines.next()
- if !ok {
- return nil, errors.New("no twitter name")
- }
- p.WWW, ok = lines.next()
- if !ok {
- return nil, errors.New("no www link")
- }
- pres.Presenters = append(pres.Presenters, p)
- }
+ pres.Presenters, err = parsePresenters(lines)
// Slides
for i := 0; ; i++ {
var slide Slide
@@ -317,3 +300,72 @@
}
return pres, nil
}
+
+func parsePresenters(lines *Lines) (pres []Presenter, err error) {
+ // This grammar demarcates presenters with blanks.
+
+ // Skip blank lines.
+ if _, ok := lines.nextNonEmpty(); !ok {
+ return nil, errors.New("unexpected EOF")
+ }
+ lines.back()
+
+ var p *Presenter
+ for {
+ text, ok := lines.next()
+ if !ok {
+ return nil, errors.New("unexpected EOF")
+ }
+
+ // If we find a slide heading, we're done.
+ if strings.HasPrefix(text, "* ") {
+ lines.back()
+ break
+ }
+
+ // If we encounter a blank we're done with this presenter.
+ if p != nil && len(text) == 0 {
+ pres = append(pres, *p)
+ p = nil
+ continue
+ }
+ if p == nil {
+ p = new(Presenter)
+ }
+
+ // Parse the line. Those that
+ // - begin with @ are twitter names,
+ // - contain slashes are links, or
+ // - contain an @ symbol are an email address.
+ // The rest is just text.
+ var el Elem
+ switch {
+ case strings.HasPrefix(text, "@"):
+ el = parseURL("http://twitter.com/" + text[1:])
+ if l, ok := el.(Link); ok {
+ l.Args = []string{text}
+ }
+ case strings.Contains(text, ":"):
+ el = parseURL(text)
+ case strings.Contains(text, "@"):
+ el = parseURL("mailto:" + text)
+ }
+ if el == nil {
+ el = Text{Lines: []string{text}}
+ }
+ p.Elem = append(p.Elem, el)
+ }
+ if p != nil {
+ pres = append(pres, *p)
+ }
+ return pres, nil
+}
+
+func parseURL(text string) Elem {
+ u, err := url.Parse(text)
+ if err != nil {
+ log.Printf("Parse(%q): %v", text, err)
+ return nil
+ }
+ return Link{URL: u}
+}
diff --git a/present/slide.tmpl b/present/slide.tmpl
index e3ecdaa..62de725 100755
--- a/present/slide.tmpl
+++ b/present/slide.tmpl
@@ -23,10 +23,9 @@
<h1>{{.Title}}</h1>
{{with .Subtitle}}<h3>{{.}}</h3>{{end}}
{{range .Presenters}}
- <p>
- {{.Name}}
- {{with .Company}}<br>{{.}}{{end}}
- </p>
+ <div class="presenter">
+ {{range .TextElem}}{{.HTML $.Template}}{{end}}
+ </div>
{{end}}
</article>
@@ -46,13 +45,9 @@
<article>
<h3>Thank you</h1>
{{range .Presenters}}
- <p>
- {{.Name}}
- {{with .Company}}<br>{{.}}{{end}}
- {{with .Gplus}}<br><a href="{{.}}">{{.}}</a>{{end}}
- {{with .Twitter}}<br><a href="http://twitter.com/{{.}}">{{.}}</a>{{end}}
- {{with .WWW}}<br><a href="{{.}}">{{.}}</a>{{end}}
- </p>
+ <div class="presenter">
+ {{range .Elem}}{{.HTML $.Template}}{{end}}
+ </div>
{{end}}
</article>
diff --git a/present/static/styles.css b/present/static/styles.css
index 1153118..08d9193 100755
--- a/present/static/styles.css
+++ b/present/static/styles.css
@@ -405,3 +405,14 @@
right: 5px;
bottom: 5px;
}
+
+/* Presenter details */
+.presenter {
+ margin-top: 20px;
+}
+.presenter p,
+.presenter .link {
+ margin: 0;
+ font-size: 28px;
+ line-height: 1.2em;
+}