go.talks/present: add .html function
R=r
CC=golang-dev
https://golang.org/cl/6726052
diff --git a/present/code.go b/present/code.go
index c60aedf..aa49ee2 100644
--- a/present/code.go
+++ b/present/code.go
@@ -81,19 +81,10 @@
SourceLine: lineno}, nil
}
-// contents reads a file by name and returns its contents as a byte slice.
-func contents(name string) ([]byte, error) {
- file, err := ioutil.ReadFile(name)
- if err != nil {
- return nil, err
- }
- return file, nil
-}
-
// code is the entry point for the '.code' present command.
func code(c Code) (template.HTML, error) {
filename := filepath.Join(filepath.Dir(c.SourceFile), c.File)
- textBytes, err := contents(filename)
+ textBytes, err := ioutil.ReadFile(filename)
if err != nil {
return "", fmt.Errorf("%s:%d: %v", c.SourceFile, c.SourceLine, err)
}
@@ -182,7 +173,7 @@
// oneLine returns the single line generated by a two-argument code invocation.
func oneLine(file, text string, arg interface{}) (line, before, after string, err error) {
- contentBytes, err := contents(file)
+ contentBytes, err := ioutil.ReadFile(file)
if err != nil {
return "", "", "", err
}
@@ -206,7 +197,7 @@
// multipleLines returns the text generated by a three-argument code invocation.
func multipleLines(file string, arg1, arg2 interface{}) (line, before, after string, err error) {
- contentBytes, err := contents(file)
+ contentBytes, err := ioutil.ReadFile(file)
lines := strings.SplitAfter(string(contentBytes), "\n")
if err != nil {
return "", "", "", err
diff --git a/present/doc.go b/present/doc.go
index 4f368d7..00b3686 100644
--- a/present/doc.go
+++ b/present/doc.go
@@ -59,6 +59,7 @@
.play y.go
.image image.jpg
.link http://foo label
+ .html file.html
Again, more text
@@ -145,6 +146,7 @@
Create a hyperlink. The syntax is 1 or 2 space-separated arguments.
The first argument is always the HTTP URL. If there is a second
argument, it is the text label to display for this link.
+
.link http://golang.org golang.org
image:
@@ -158,5 +160,13 @@
.image images/betsy.jpg 100 200
+html:
+
+The function html includes the contents of the specified file as
+unescaped HTML. This is useful for including custom HTML elements
+that cannot be created using only the slide format.
+
+ .html file.html
+
*/
package main
diff --git a/present/html.go b/present/html.go
new file mode 100644
index 0000000..4c893c3
--- /dev/null
+++ b/present/html.go
@@ -0,0 +1,32 @@
+package main
+
+import (
+ "errors"
+ "html/template"
+ "io/ioutil"
+ "path/filepath"
+ "strings"
+)
+
+func init() {
+ Register("html", parseHTML, nil)
+}
+
+func parseHTML(fileName string, lineno int, text string) (Elem, error) {
+ p := strings.Fields(text)
+ if len(p) != 2 {
+ return nil, errors.New("invalid .html args")
+ }
+ name := filepath.Join(filepath.Dir(fileName), p[1])
+ b, err := ioutil.ReadFile(name)
+ if err != nil {
+ return nil, err
+ }
+ return HTML(b), nil
+}
+
+type HTML string
+
+func (s HTML) HTML(*template.Template) (template.HTML, error) {
+ return template.HTML(s), nil
+}
diff --git a/present/parse.go b/present/parse.go
index 108b9b1..327d103 100644
--- a/present/parse.go
+++ b/present/parse.go
@@ -11,6 +11,7 @@
"fmt"
"html/template"
"io"
+ "io/ioutil"
"log"
"net/url"
"path/filepath"
@@ -35,8 +36,10 @@
if len(name) == 0 || name[0] == ';' {
panic("bad name in Register: " + name)
}
- funcs[name] = function
parsers["."+name] = parser
+ if function != nil {
+ funcs[name] = function
+ }
}
// renderSlides reads the slide file, builds its template representation,
@@ -143,7 +146,7 @@
}
func readLines(name string) (*Lines, error) {
- contentBytes, err := contents(name)
+ contentBytes, err := ioutil.ReadFile(name)
if err != nil {
return nil, err
}