blob: 4c40cee8e63df7773943953aa26c801553d0d93c [file] [log] [blame]
// 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 or at
// https://developers.google.com/open-source/licenses/bsd.
package gosrc
import (
"path/filepath"
"regexp"
"time"
)
type Presentation struct {
Filename string
Files map[string][]byte
Updated time.Time
}
type presBuilder struct {
filename string
data []byte
resolveURL func(fname string) string
fetch func(fnames []string) ([]*File, error)
}
var assetPat = regexp.MustCompile(`(?m)^\.(play|code|image|background|iframe|html)\s+(?:-\S+\s+)*(\S+)`)
func (b *presBuilder) build() (*Presentation, error) {
var data []byte
var fnames []string
i := 0
for _, m := range assetPat.FindAllSubmatchIndex(b.data, -1) {
name := filepath.Clean(string(b.data[m[4]:m[5]]))
switch string(b.data[m[2]:m[3]]) {
case "iframe", "image", "background":
data = append(data, b.data[i:m[4]]...)
data = append(data, b.resolveURL(name)...)
case "html":
// TODO: sanitize and fix relative URLs in HTML.
data = append(data, "\nERROR: .html not supported\n"...)
case "play", "code":
data = append(data, b.data[i:m[5]]...)
found := false
for _, n := range fnames {
if n == name {
found = true
break
}
}
if !found {
fnames = append(fnames, name)
}
default:
data = append(data, "\nERROR: unknown command\n"...)
}
i = m[5]
}
data = append(data, b.data[i:]...)
files, err := b.fetch(fnames)
if err != nil {
return nil, err
}
pres := &Presentation{
Updated: time.Now().UTC(),
Filename: b.filename,
Files: map[string][]byte{b.filename: data},
}
for _, f := range files {
pres.Files[f.Name] = f.Data
}
return pres, nil
}