mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-11-04 01:19:20 +08:00 
			
		
		
		
	templates: Add readFile action that does not evaluate templates (#5553)
				
					
				
			* Create an includeRaw template function to include a file without parsing it as a template. Some formatting fixes * Rename to readFile, various docs adjustments --------- Co-authored-by: Francis Lavoie <lavofr@gmail.com>
This commit is contained in:
		@ -88,7 +88,11 @@ func init() {
 | 
			
		||||
//
 | 
			
		||||
// ##### `httpInclude`
 | 
			
		||||
//
 | 
			
		||||
// Includes the contents of another file by making a virtual HTTP request (also known as a sub-request). The URI path must exist on the same virtual server because the request does not use sockets; instead, the request is crafted in memory and the handler is invoked directly for increased efficiency.
 | 
			
		||||
// Includes the contents of another file, and renders it in-place,
 | 
			
		||||
// by making a virtual HTTP request (also known as a sub-request).
 | 
			
		||||
// The URI path must exist on the same virtual server because the
 | 
			
		||||
// request does not use sockets; instead, the request is crafted in
 | 
			
		||||
// memory and the handler is invoked directly for increased efficiency.
 | 
			
		||||
//
 | 
			
		||||
// ```
 | 
			
		||||
// {{httpInclude "/foo/bar?q=val"}}
 | 
			
		||||
@ -96,7 +100,13 @@ func init() {
 | 
			
		||||
//
 | 
			
		||||
// ##### `import`
 | 
			
		||||
//
 | 
			
		||||
// Imports the contents of another file and adds any template definitions to the template stack. If there are no defitions, the filepath will be the defition name. Any {{ define }} blocks will be accessible by {{ template }} or {{ block }}. Imports must happen before the template or block action is called
 | 
			
		||||
// Reads and returns the contents of another file, and parses it
 | 
			
		||||
// as a template, adding any template definitions to the template
 | 
			
		||||
// stack. If there are no definitions, the filepath will be the
 | 
			
		||||
// definition name. Any {{ define }} blocks will be accessible by
 | 
			
		||||
// {{ template }} or {{ block }}. Imports must happen before the
 | 
			
		||||
// template or block action is called. Note that the contents are
 | 
			
		||||
// NOT escaped, so you should only import trusted template files.
 | 
			
		||||
//
 | 
			
		||||
// **filename.html**
 | 
			
		||||
// ```
 | 
			
		||||
@ -113,13 +123,26 @@ func init() {
 | 
			
		||||
//
 | 
			
		||||
// ##### `include`
 | 
			
		||||
//
 | 
			
		||||
// Includes the contents of another file and renders in-place. Optionally can pass key-value pairs as arguments to be accessed by the included file.
 | 
			
		||||
// Includes the contents of another file, rendering it in-place.
 | 
			
		||||
// Optionally can pass key-value pairs as arguments to be accessed
 | 
			
		||||
// by the included file. Note that the contents are NOT escaped,
 | 
			
		||||
// so you should only include trusted template files.
 | 
			
		||||
//
 | 
			
		||||
// ```
 | 
			
		||||
// {{include "path/to/file.html"}}  // no arguments
 | 
			
		||||
// {{include "path/to/file.html" "arg1" 2 "value 3"}}  // with arguments
 | 
			
		||||
// ```
 | 
			
		||||
//
 | 
			
		||||
// ##### `readFile`
 | 
			
		||||
//
 | 
			
		||||
// Reads and returns the contents of another file, as-is.
 | 
			
		||||
// Note that the contents are NOT escaped, so you should
 | 
			
		||||
// only read trusted files.
 | 
			
		||||
//
 | 
			
		||||
// ```
 | 
			
		||||
// {{readFile "path/to/file.html"}}
 | 
			
		||||
// ```
 | 
			
		||||
//
 | 
			
		||||
// ##### `listFiles`
 | 
			
		||||
//
 | 
			
		||||
// Returns a list of the files in the given directory, which is relative to the template context's file root.
 | 
			
		||||
@ -130,10 +153,10 @@ func init() {
 | 
			
		||||
//
 | 
			
		||||
// ##### `markdown`
 | 
			
		||||
//
 | 
			
		||||
// Renders the given Markdown text as HTML. This uses the
 | 
			
		||||
// Renders the given Markdown text as HTML and returns it. This uses the
 | 
			
		||||
// [Goldmark](https://github.com/yuin/goldmark) library,
 | 
			
		||||
// which is CommonMark compliant. It also has these plugins
 | 
			
		||||
// enabled: Github Flavored Markdown, Footnote and syntax
 | 
			
		||||
// which is CommonMark compliant. It also has these extensions
 | 
			
		||||
// enabled: Github Flavored Markdown, Footnote, and syntax
 | 
			
		||||
// highlighting provided by [Chroma](https://github.com/alecthomas/chroma).
 | 
			
		||||
//
 | 
			
		||||
// ```
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,7 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/Masterminds/sprig/v3"
 | 
			
		||||
	"github.com/alecthomas/chroma/v2/formatters/html"
 | 
			
		||||
	chromahtml "github.com/alecthomas/chroma/v2/formatters/html"
 | 
			
		||||
	"github.com/caddyserver/caddy/v2"
 | 
			
		||||
	"github.com/caddyserver/caddy/v2/modules/caddyhttp"
 | 
			
		||||
	"github.com/dustin/go-humanize"
 | 
			
		||||
@ -74,6 +74,7 @@ func (c *TemplateContext) NewTemplate(tplName string) *template.Template {
 | 
			
		||||
	// add our own library
 | 
			
		||||
	c.tpl.Funcs(template.FuncMap{
 | 
			
		||||
		"include":          c.funcInclude,
 | 
			
		||||
		"readFile":         c.funcReadFile,
 | 
			
		||||
		"import":           c.funcImport,
 | 
			
		||||
		"httpInclude":      c.funcHTTPInclude,
 | 
			
		||||
		"stripHTML":        c.funcStripHTML,
 | 
			
		||||
@ -123,6 +124,23 @@ func (c TemplateContext) funcInclude(filename string, args ...any) (string, erro
 | 
			
		||||
	return bodyBuf.String(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// funcReadFile returns the contents of a filename relative to the site root.
 | 
			
		||||
// Note that included files are NOT escaped, so you should only include
 | 
			
		||||
// trusted files. If it is not trusted, be sure to use escaping functions
 | 
			
		||||
// in your template.
 | 
			
		||||
func (c TemplateContext) funcReadFile(filename string) (string, error) {
 | 
			
		||||
	bodyBuf := bufPool.Get().(*bytes.Buffer)
 | 
			
		||||
	bodyBuf.Reset()
 | 
			
		||||
	defer bufPool.Put(bodyBuf)
 | 
			
		||||
 | 
			
		||||
	err := c.readFileToBuffer(filename, bodyBuf)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return bodyBuf.String(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// readFileToBuffer reads a file into a buffer
 | 
			
		||||
func (c TemplateContext) readFileToBuffer(filename string, bodyBuf *bytes.Buffer) error {
 | 
			
		||||
	if c.Root == nil {
 | 
			
		||||
@ -315,7 +333,7 @@ func (TemplateContext) funcMarkdown(input any) (string, error) {
 | 
			
		||||
			extension.Footnote,
 | 
			
		||||
			highlighting.NewHighlighting(
 | 
			
		||||
				highlighting.WithFormatOptions(
 | 
			
		||||
					html.WithClasses(true),
 | 
			
		||||
					chromahtml.WithClasses(true),
 | 
			
		||||
				),
 | 
			
		||||
			),
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user