Пример #1
0
func RenderTemplate(path string, input []byte, metadata map[string]interface{}) []byte {
	R := func(relativeFilename string) string {
		filename := filepath.Join(filepath.Dir(path), relativeFilename)
		return string(RenderTemplate(filename, Read(filename), metadata))
	}
	importhtml := func(relativeFilename string) template.HTML {
		return template.HTML(R(relativeFilename))
	}
	importcss := func(relativeFilename string) template.CSS {
		return template.CSS(R(relativeFilename))
	}
	importjs := func(relativeFilename string) template.JS {
		return template.JS(R(relativeFilename))
	}

	templateName := Relative(*sourceDir, path)
	funcMap := template.FuncMap{
		"importhtml": importhtml,
		"importcss":  importcss,
		"importjs":   importjs,
		"sorted":     SortedValues,
	}

	tmpl, err := template.New(templateName).Funcs(funcMap).Parse(string(input))
	if err != nil {
		Fatalf("Render Template %s: Parse: %s", path, err)
	}

	output := bytes.Buffer{}
	if err = tmpl.Execute(&output, metadata); err != nil {
		Fatalf("Render Template %s: Execute: %s", path, err)
	}

	return output.Bytes()
}
Пример #2
0
func init() {
	HtmlFuncBoot.Register(func(w *Web) {
		// HTML Marksafe
		w.HtmlFunc["html"] = func(str string) html.HTML {
			return html.HTML(str)
		}

		// HTML Attr MarkSafe
		w.HtmlFunc["htmlattr"] = func(str string) html.HTMLAttr {
			return html.HTMLAttr(str)
		}

		// JS Marksafe
		w.HtmlFunc["js"] = func(str string) html.JS {
			return html.JS(str)
		}

		// JS String Marksafe
		w.HtmlFunc["jsstr"] = func(str string) html.JSStr {
			return html.JSStr(str)
		}

		// CSS Marksafe
		w.HtmlFunc["css"] = func(str string) html.CSS {
			return html.CSS(str)
		}
	})
}
Пример #3
0
// colors generates the CSS rules for coverage colors.
func colors() template.CSS {
	var buf bytes.Buffer
	for i := 0; i < 11; i++ {
		fmt.Fprintf(&buf, ".cov%v { color: %v }\n", i, rgb(i))
	}
	return template.CSS(buf.String())
}
Пример #4
0
func renderArticle(c interface{}, path string, arg string) {
	// inject content
	stylePath := resolveFilename("style.css")
	coverPath := resolveFilename("_cover")

	styleContent, _ := ioutil.ReadFile(stylePath)
	coverJSON, _ := ioutil.ReadFile(coverPath)

	article := readArticle(path)

	data := gin.H{
		"title":      filepath.Base(path),
		"article":    template.JS(article.data),
		"useMathjax": article.useMathjax,
		"style":      template.CSS(styleContent),
		"cover":      template.JS(coverJSON),
	}

	switch target := c.(type) {
	case *gin.Context:
		// arg is the template used
		target.HTML(http.StatusOK, arg, data)
	case *template.Template:
		// arg is the file to be written to
		w, err := createFile(arg)
		if err != nil {
			panic(err.Error())
		}
		target.Execute(w, data)
	}
}
Пример #5
0
// ForegroundColor calculates the text color for labels based
// on their background color.
func (l *Label) ForegroundColor() template.CSS {
	if strings.HasPrefix(l.Color, "#") {
		if color, err := strconv.ParseUint(l.Color[1:], 16, 64); err == nil {
			r := float32(0xFF & (color >> 16))
			g := float32(0xFF & (color >> 8))
			b := float32(0xFF & color)
			luminance := (0.2126*r + 0.7152*g + 0.0722*b) / 255

			if luminance < 0.5 {
				return template.CSS("#fff")
			}
		}
	}

	// default to black
	return template.CSS("#000")
}
Пример #6
0
func colorNick(s string) template.CSS {
	hue := uint(0)
	for _, c := range s {
		hue *= 17
		hue += uint(c)
	}
	style := fmt.Sprintf("color: hsl(%d, 40%%, 50%%)", hue%360)
	return template.CSS(style)
}
// An example http.Handler that serves a template
func TemplateHandler(w http.ResponseWriter, r *http.Request) {
	// The JS() and CSS() functions will safely escape the given string
	// according to the requested format.
	attrs := map[string]interface{}{
		"Title": "I am a Title from Attributes",
		"JS":    template.JS("console.log('I am safely injected JavaScript!');"),
		"CSS":   template.CSS("p { color: blue; border: 1px solid #aaa }"),
	}
	example.Execute(w, attrs)
}
Пример #8
0
func (c *Chart) CSS() template.CSS {
	h, w := c.Height, c.Width
	if h == 0 {
		h = 150
	}
	if w == 0 {
		w = 300
	}
	return template.CSS(fmt.Sprintf("width:%dpx;height:%dpx", w, h))
}
Пример #9
0
func newInvitationEmailHTMLContent(title, inlineStyles, name, company, invitedBy, link string) (string, error) {
	// Layout
	layoutContents, err := ioutil.ReadFile(htmlEmailLayout)
	if err != nil {
		return "", err
	}
	layoutTmpl, err := htmlTemplate.New(htmlEmailLayout).Parse(string(layoutContents))
	if err != nil {
		return "", err
	}

	// Content
	templateContents, err := ioutil.ReadFile(invitationEmailTemplateHTML)
	if err != nil {
		return "", err
	}
	tmpl, err := htmlTemplate.New(invitationEmailTemplateHTML).Parse(string(templateContents))
	if err != nil {
		return "", err
	}

	var (
		inventory                   map[string]interface{}
		parsedContent, parsedLayout bytes.Buffer
	)

	// Parse the content template
	inventory = map[string]interface{}{
		"name":          name,
		"company":       company,
		"invitedBy":     invitedBy,
		"invitationURL": link,
	}
	if err := tmpl.Execute(&parsedContent, inventory); err != nil {
		return "", err
	}

	// Insert the content into the layout
	inventory = map[string]interface{}{
		"title":        title,
		"inlineStyles": htmlTemplate.CSS(inlineStyles),
		"content":      htmlTemplate.HTML(parsedContent.String()),
		"company":      company,
	}
	if err := layoutTmpl.Execute(&parsedLayout, inventory); err != nil {
		return "", err
	}

	return parsedLayout.String(), nil
}
Пример #10
0
func init() {
	//初始化基本模板函数
	//until(start, end int) []int:生成一个从start到end的数组
	//time(t time.Time) string:返回时间字符串2006-01-02 15:04:05
	//date(t time.Time) string:返回日期字符串2006-01-02
	//tocss(s string) template.CSS:转换字符串为CSS
	//tohtml(s string) template.HTML:转换字符串为HTML
	//toattr(s string) template.HTMLAttr:转换字符串为HTMLAttr
	//tojs(s string) template.JS:转换字符串为JS
	//tojsstr(s string) template.JSStr:转换字符串为JSStr
	//tourl(s string) template.URL:转换字符串为URL
	commonFuncMap = template.FuncMap{
		"until": func(start, end int) []int {
			if end >= start {
				var length = end - start + 1
				var result = make([]int, length)
				for i := 0; i < length; i++ {
					result[i] = start + i
				}
				return result
			}
			return []int{}
		},
		"time": func(t time.Time) string {
			return t.Format("2006-01-02 15:04:05")
		},
		"date": func(t time.Time) string {
			return t.Format("2006-01-02")
		},
		"tocss": func(s string) template.CSS {
			return template.CSS(s)
		},
		"tohtml": func(s string) template.HTML {
			return template.HTML(s)
		},
		"toattr": func(s string) template.HTMLAttr {
			return template.HTMLAttr(s)
		},
		"tojs": func(s string) template.JS {
			return template.JS(s)
		},
		"tojsstr": func(s string) template.JSStr {
			return template.JSStr(s)
		},
		"tourl": func(s string) template.URL {
			return template.URL(s)
		},
	}
}
Пример #11
0
// openDiffs diffs the given files and writes the result to a tempfile,
// then opens it in the gui.
func render(d *delta.DiffSolution, pathFrom, pathTo, pathBase string, config Config) (*bytes.Buffer, error) {
	change := changeModified
	if pathTo == "/dev/null" {
		change = changeDeleted
	} else if pathFrom == "/dev/null" {
		change = changeAdded
	}

	// normalize paths so we don't have tmp on the path
	tmpFrom := strings.HasPrefix(pathFrom, os.TempDir())
	tmpTo := strings.HasPrefix(pathTo, os.TempDir())
	if tmpFrom && !tmpTo {
		pathFrom = pathTo
	} else if !tmpFrom && tmpTo {
		pathTo = pathFrom
	}

	wd, _ := os.Getwd()
	html := formatter.HTML(d)
	m := &Metadata{
		From:      pathFrom,
		To:        pathTo,
		Merged:    pathBase,
		Dir:       wd,
		Change:    change,
		Hash:      md5sum(html),
		DirHash:   md5sum(wd),
		Timestamp: time.Now().UnixNano() / 1000000, // convert to millis
	}
	meta, _ := json.Marshal(m)
	cfg, _ := json.Marshal(config)
	tmpl := template.Must(template.New("compare").Parse(getAsset("compare.html")))
	buf := &bytes.Buffer{}
	err := tmpl.Execute(buf, map[string]interface{}{
		"metadata": template.JS(string(meta)),
		"config":   template.JS(cfg),
		"content":  template.HTML(html),
		"CSS":      template.CSS(getAsset("app.css")),
		"JS": map[string]interface{}{
			"mithril":   template.JS(getAsset("vendor/mithril.min.js")),
			"mousetrap": template.JS(getAsset("vendor/mousetrap.min.js")),
			"highlight": template.JS(getAsset("vendor/highlight.min.js")),
			"pouchdb":   template.JS(getAsset("vendor/pouchdb.min.js")),
			"app":       template.JS(getAsset("app.js")),
		},
	})
	return buf, err
}
Пример #12
0
func TestToString(t *testing.T) {
	var foo interface{} = "one more time"
	assert.Equal(t, ToString(8), "8")
	assert.Equal(t, ToString(int64(16)), "16")
	assert.Equal(t, ToString(8.12), "8.12")
	assert.Equal(t, ToString([]byte("one time")), "one time")
	assert.Equal(t, ToString(template.HTML("one time")), "one time")
	assert.Equal(t, ToString(template.URL("http://somehost.foo")), "http://somehost.foo")
	assert.Equal(t, ToString(template.JS("(1+2)")), "(1+2)")
	assert.Equal(t, ToString(template.CSS("a")), "a")
	assert.Equal(t, ToString(template.HTMLAttr("a")), "a")
	assert.Equal(t, ToString(foo), "one more time")
	assert.Equal(t, ToString(nil), "")
	assert.Equal(t, ToString(true), "true")
	assert.Equal(t, ToString(false), "false")
}
Пример #13
0
// Must be called after flag.Parse()
func Init(tlsCertPath, tlsKeyPath, staticPath string) {
	loadTemplates()
	b, err := ioutil.ReadFile(filepath.Join(staticPath, "critical.min.css"))
	if err != nil {
		log.Fatal(err)
	}
	CriticalCss = template.CSS(string(b))
	addrs := strings.Split(*sourceBackends, ",")
	SourceBackendStubs = make([]proto.SourceBackendClient, len(addrs))
	for idx, addr := range addrs {
		conn, err := grpcutil.DialTLS(addr, tlsCertPath, tlsKeyPath)
		if err != nil {
			log.Fatalf("could not connect to %q: %v", addr, err)
		}
		SourceBackendStubs[idx] = proto.NewSourceBackendClient(conn)
	}
}
Пример #14
0
func (m middlewareView) Init(app *App) error {
	app.requestMiddlewares = append(app.requestMiddlewares, requestMiddlewareView)

	templates := template.New("")
	templateFuncs := template.FuncMap{}

	templateFuncs["Plain"] = func(data string) template.HTML {
		return template.HTML(data)
	}

	templateFuncs["CSS"] = func(data string) template.CSS {
		return template.CSS(data)
	}

	templates = templates.Funcs(templateFuncs)

	app.data["templates"] = templates
	app.data["templateFuncs"] = templateFuncs
	return nil
}
Пример #15
0
func (doc *Content) AddFile(f string) error {
	switch path.Ext(f) {
	case ".js":
		data, err := ioutil.ReadFile(f)
		if err != nil {
			return err
		}
		doc.JS = append(doc.JS, template.JS(data))
	case ".css":
		data, err := ioutil.ReadFile(f)
		if err != nil {
			return err
		}
		doc.CSS = append(doc.CSS, template.CSS(data))
	case ".html":
		data, err := ioutil.ReadFile(f)
		if err != nil {
			return err
		}
		doc.HTML = append(doc.HTML, template.HTML(data))
	}

	return nil
}
Пример #16
0
func SafeCSS(text string) template.CSS {
	return template.CSS(text)
}
Пример #17
0
// safeCSS returns a given string as html/template CSS content.
func safeCSS(a interface{}) template.CSS {
	return template.CSS(cast.ToString(a))
}
Пример #18
0
func Css(raw string) template.CSS {
	return template.CSS(raw)
}
Пример #19
0
func main() {
	s := db.Connect()
	defer db.Disconnect(s)
	craniumDB := db.SetDB(s)

	r := gin.Default()

	// Set up Gin cookies
	store := sessions.NewCookieStore([]byte("pladjamaicanwifflepoof"))
	r.Use(sessions.Sessions("cranium_session", store))

	var title string

	var de model.DataEntry

	r.LoadHTMLGlob("templates/*")
	r.Static("/assets", "./assets")

	// Routes
	r.GET("/", func(c *gin.Context) {
		session := sessions.Default(c)
		craniumId := session.Get("cranium_id")
		if craniumId == nil {
			// Insert a new user if the user has no cookie
			newCraniumId := randomString(30)
			db.InsertNewVisitor(craniumDB, newCraniumId)
			session.Set("cranium_id", newCraniumId)
			session.Save()
			title = newCraniumId
			readfile, _ := os.Open("templates/index-tmpl.html")
			outfile, _ := os.Create("templates/index.html")
			defer readfile.Close()
			defer outfile.Close()
			// Get all the Ids for tags in question
			aImpIds, pImpIds, imgImpIds, aNimpIds, pNimpIds, imgNimpIds := preprocess.GenerateTags(readfile, outfile)
			var atags []model.Atag
			var ptags []model.Ptag
			var imgtags []model.Imgtag

			for _, impId := range aImpIds {
				atag := model.AtagDefault
				atag.Id = impId
				atag.Important = true
				atags = append(atags, atag)
			}
			for _, impId := range pImpIds {
				ptag := model.PtagDefault
				ptag.Id = impId
				ptag.Important = true
				ptags = append(ptags, ptag)
			}
			for _, impId := range imgImpIds {
				imgtag := model.ImgtagDefault
				imgtag.Id = impId
				imgtag.Important = true
				imgtags = append(imgtags, imgtag)
			}
			for _, impId := range aNimpIds {
				atag := model.AtagDefault
				atag.Id = impId
				atag.Important = false
				atags = append(atags, atag)
			}
			for _, impId := range pNimpIds {
				ptag := model.PtagDefault
				ptag.Id = impId
				ptag.Important = false
				ptags = append(ptags, ptag)
			}
			for _, impId := range imgNimpIds {
				imgtag := model.ImgtagDefault
				imgtag.Id = impId
				imgtag.Important = false
				imgtags = append(imgtags, imgtag)
			}
			de = db.InsertNewDataEntry(craniumDB, newCraniumId, atags, ptags, imgtags)
		} else {
			readfile, _ := os.Open("templates/index-tmpl.html")
			outfile, _ := os.Create("templates/index.html")
			defer readfile.Close()
			defer outfile.Close()
			// Get all the Ids for tags in question
			preprocess.GenerateTags(readfile, outfile)
			// The user already exists, so ask the database for attributes
			title = craniumId.(string)
			visitor := db.FetchVisitor(craniumDB, craniumId.(string))
			de = visitor.Data[len(visitor.Data)-1]
		}
		craniumcss := cssgen.GenCss(de)
		c.HTML(http.StatusOK, "index.html", gin.H{
			"title":      "cranium.css | " + title,
			"craniumcss": template.CSS(craniumcss),
		})
	})

	type Entities struct {
		Data string `json:"data" binding:"required"`
	}

	r.POST("/data", func(c *gin.Context) {
		session := sessions.Default(c)
		craniumId := session.Get("cranium_id")
		var ents Entities
		c.BindJSON(&ents)
		c.JSON(200, ents)
		tags := deserialize(ents.Data)
		for _, tag := range tags {
			tag_pick := strings.Split(string(tag.Id), "-")
			if string(tag_pick[1][0]) == "a" {
				db.UpdateAtagField(craniumDB, craniumId.(string), tag)
			} else if string(tag_pick[1][0]) == "p" {
				db.UpdatePtagField(craniumDB, craniumId.(string), tag)
			} else if string(tag_pick[1][0]) == "i" {
				db.UpdateImgtagField(craniumDB, craniumId.(string), tag)
			}
		}
		// CSV the data
		app := "python"
		cmd := exec.Command(app, "learn/csvgen.py", craniumId.(string), "-de0")
		fmt.Println()
		out, err := cmd.Output()
		if err != nil {
			println(err.Error())
			return
		}
		fmt.Println(string(out))

		fmt.Println(craniumId.(string))

		cmd1 := exec.Command(app, "learn/classify.py", "learn/de_td0_a.csv", "a", craniumId.(string), "", "", "")
		cmd1.Output()

		cmd2 := exec.Command(app, "learn/classify.py", "learn/de_td0_p.csv", "p", craniumId.(string), "", "", "")
		cmd2.Output()

		cmd3 := exec.Command(app, "learn/classify.py", "learn/de_td0_img.csv", "img", craniumId.(string), "", "", "")
		cmd3.Output()

		cmd4 := exec.Command(app, "learn/classify.py", "", "solve", craniumId.(string), "learn/training/atag.csv", "learn/training/ptag.csv", "learn/training/imgtag.csv")
		cmd4.Output()

		// Run genetic

		// Save new DE entry

		// Export DE to CSV
		// cmd4 := exec.Command(app, "learn/csvgen.py", craniumId.(string))
		// cmd4.Output()

		// Concat CSV with train

		// run SVM
		// python learn/svm.py learn/training/imgtag.csv img
		// cmd5 := exec.Command(app, "learn/svm.py", "learn/training/atag.csv", "a")
		// cmd5.Output()

		// cmd6 := exec.Command(app, "learn/svm.py", "learn/training/ptag.csv", "p")
		// cmd5.Output()

		// cmd7 := exec.Command(app, "learn/svm.py", "learn/training/imgtag.csv", "img")
		// cmd5.Output()
	})

	r.Run(":1225")
}
Пример #20
0
func safeCSSFunc(data string) template.CSS {
	return template.CSS(data)
}
Пример #21
0
func linearGradient(path string) template.CSS {
	return template.CSS(fmt.Sprintf("linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url('%s')", path))
}
Пример #22
0
func (c *PageModel) UnescapeCSS() template.CSS {
	return template.CSS(c.CSS)
}
Пример #23
0
func newFunctionsFor(renderer *Renderer) template.FuncMap {
	return template.FuncMap{
		"transformIdType": renderer.transformIDType,
		"getDisplayIdOf":  renderer.getDisplayIDOf,
		"renderValueType": renderer.renderValueType,
		"renderMarkdown":  renderer.renderMarkdown,
		"toSimple": func(definition Definition) *SimpleDefinition {
			if result, ok := definition.(*SimpleDefinition); ok {
				return result
			}
			return nil
		},
		"toObject": func(definition Definition) *ObjectDefinition {
			if result, ok := definition.(*ObjectDefinition); ok {
				return result
			}
			return nil
		},
		"toEnum": func(definition Definition) *EnumDefinition {
			if result, ok := definition.(*EnumDefinition); ok {
				return result
			}
			return nil
		},
		"toProperty": func(definition Definition) *PropertyDefinition {
			if result, ok := definition.(*PropertyDefinition); ok {
				return result
			}
			return nil
		},
		"toElement": func(definition Definition) *ElementDefinition {
			if result, ok := definition.(*ElementDefinition); ok {
				return result
			}
			return nil
		},
		"include": func(name string, data interface{}) (template.HTML, error) {
			tmpl, err := parseTemplate(renderer.Project, "includes/"+name, renderer.Functions)
			if err != nil {
				return "", err
			}
			return tmpl.Execute(data)
		},
		"includeJavaScript": func(name string) (template.JS, error) {
			content, err := ioutil.ReadFile(renderer.Project.SrcRootPath + "/manual/templates/scripts/" + name + ".js")
			if err != nil {
				return "", err
			}
			return template.JS(content), err
		},
		"includeCss": func(name string) (template.CSS, error) {
			content, err := ioutil.ReadFile(renderer.Project.SrcRootPath + "/manual/templates/styles/" + name + ".css")
			if err != nil {
				return "", err
			}
			return template.CSS(content), err
		},
		"includeMarkdown": func(name string, headerTypeStart int, headerIdPrefix string, data interface{}) (template.HTML, error) {
			source := renderer.Project.SrcRootPath + "/manual/includes/" + name + ".md"
			content, err := ioutil.ReadFile(source)
			if err != nil {
				return "", err
			}
			html, err := renderer.renderMarkdownWithContext(string(content), nil, headerTypeStart, headerIdPrefix)
			if err != nil {
				return "", err
			}
			tmpl, err := template.New(source).Funcs(renderer.Functions).Parse(string(html))
			if err != nil {
				return "", err
			}
			buf := new(bytes.Buffer)
			err = tmpl.ExecuteTemplate(buf, source, data)
			if err != nil {
				return "", err
			}
			return template.HTML(buf.String()), nil
		},
		"includeLicense": func() (string, error) {
			content, err := ioutil.ReadFile(renderer.Project.SrcRootPath + "/LICENSE")
			if err != nil {
				return "", err
			}
			return string(content), err
		},
		"includeAppUsageOf": func(executableType app.ExecutableType, app *cli.App) template.HTML {
			app.HelpName = executableType.String()
			buf := new(bytes.Buffer)
			cli.HelpPrinter(buf, cli.AppHelpTemplate, app)
			content := buf.String()
			content = renderer.replaceUsageEnvVarDisplaysIfNeeded(content)
			return template.HTML(content)
		},
		"collectExamples":           renderer.collectExamples,
		"transformElementHtmlId":    renderer.transformElementHTMLID,
		"renderDefinitionStructure": renderer.renderDefinitionStructure,
	}
}
Пример #24
0
func rawCSS(text string) template.CSS {
	return template.CSS(text)
}
Пример #25
0
		wait()
		fmt.Printf("%T: %#v", i, i)
		wait()
		if err := t.Execute(os.Stdout, fmt.Sprintf("%v", i)); err != nil {
			log.Println(err)
		}
		wait()
		if err := t.Execute(os.Stdout, i); err != nil {
			log.Println(err)
		}
		fmt.Println("\n")
	}
	wait()
}

var data = []interface{}{
	"safe",
	"blue",
	template.URL("O'Reilly: How are <i>you</i>?"), // unsafe
	template.HTML("<b>Hello!</b>"),
	template.HTMLAttr(`alttext="Alt"`),
	template.JS(`(x + y * z())`),
	template.CSS(`background-color: blue;`),
}

var buf = bufio.NewReader(os.Stdin)

func wait() {
	buf.ReadLine()
}
Пример #26
0
func main() {
	rc := 0
	defer func() {
		os.Exit(rc)
	}()

	log.SetFlags(0)

	useText := false
	mainTemplate := "index.tem"
	outputPath := "-"
	newline := true

	flag.StringVar(&mainTemplate, "template", mainTemplate, "the `template` to execute")
	flag.StringVar(&dataDir, "data-dir", dataDir, "`directory` containing templates and other data")
	flag.StringVar(&outputPath, "o", outputPath, "`path` to write output to. defaults to stdout (- or empty string).")
	flag.BoolVar(&useText, "text", false, "whether to skip HTML-specific encoding in templates")
	flag.BoolVar(&newline, "newline", true, "whether to write a trailing newline at the end of each output (per YAML file)")
	flag.Parse()

	if flag.NArg() == 0 {
		log.Println("no command given, exiting with status 1")
		rc = 1
		return
	}

	var mode int
	switch flag.Arg(0) {
	case "render":
		mode = modeRender
	case "yaml":
		mode = modeYAML
	default:
		log.Printf("unrecognized command: %q", flag.Arg(0))
		rc = 1
		return
	}

	var output io.Writer = os.Stdout
	switch outputPath {
	case "", "-":
	// Stdout - default
	default:
		if fi, err := os.Create(outputPath); err != nil {
			log.Printf("cannot open %s for writing: %v", outputPath, err)
			rc = 1
			return
		} else {
			defer func() {
				if err := fi.Close(); err != nil {
					log.Printf("warning: unable to close %s on shutdown: %v", err)
				}
			}()
			output = fi
		}
	}

	defer func() {
		if rc != 1 && newline {
			io.WriteString(output, "\n")
		}
	}()

	if mode == modeYAML {
		if err := generateYAML(output); err != nil {
			rc = 1
		}
		return
	}

	if useText {
		tx, err := textt.New("root").
			Funcs(map[string]interface{}{
				"embed":   readFile,
				"html":    nopstring,
				"attr":    nopstring,
				"css":     nopstring,
				"js":      nopstring,
				"linkify": linkify,
			}).
			ParseGlob(filepath.Join(dataDir, "*.tem"))

		if err != nil {
			log.Println("error parsing template as text:", err)
			rc = 1
			return
		}

		formatter = tx
	} else {
		tx, err := htmlt.New("root").
			Funcs(map[string]interface{}{
				"embed":   readFile,
				"html":    func(s string) htmlt.HTML { return htmlt.HTML(s) },
				"attr":    func(s string) htmlt.HTMLAttr { return htmlt.HTMLAttr(s) },
				"css":     func(s string) htmlt.CSS { return htmlt.CSS(s) },
				"js":      func(s string) htmlt.JS { return htmlt.JS(s) },
				"linkify": func(s string) htmlt.HTML { return htmlt.HTML(linkify(s)) },
			}).
			ParseGlob(filepath.Join(dataDir, "*.tem"))

		if err != nil {
			log.Println("error parsing template as html:", err)
			rc = 1
			return
		}

		escape = htmlt.HTMLEscapeString
		formatter = tx
	}

	args := flag.Args()[1:]
	if len(args) == 0 {
		args = []string{"-"}
	}

	for _, arg := range args {
		resume, err := readResumeFromFile(arg)
		if err != nil {
			rc = 1
			return
		}

		var buf bytes.Buffer
		if err = formatter.ExecuteTemplate(&buf, mainTemplate, resume); err != nil {
			log.Println("cannot execute template:", err)
			rc = 1
			return
		}

		b := bytes.Trim(buf.Bytes(), whitespace)
		for len(b) > 0 {
			n, err := output.Write(b)
			if err != nil && err != io.ErrShortWrite {
				log.Println("cannot write to output:", err)
				rc = 1
				return
			}
			b = b[n:]
		}
	}
}