summaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/a-h/templ/jsonscript.go
blob: 6e881747ace7d256f2355d8eb023ca4bc820166a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package templ

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
)

var _ Component = JSONScriptElement{}

// JSONScript renders a JSON object inside a script element.
// e.g. <script type="application/json">{"foo":"bar"}</script>
func JSONScript(id string, data any) JSONScriptElement {
	return JSONScriptElement{
		ID:    id,
		Type:  "application/json",
		Data:  data,
		Nonce: GetNonce,
	}
}

// WithType sets the value of the type attribute of the script element.
func (j JSONScriptElement) WithType(t string) JSONScriptElement {
	j.Type = t
	return j
}

// WithNonceFromString sets the value of the nonce attribute of the script element to the given string.
func (j JSONScriptElement) WithNonceFromString(nonce string) JSONScriptElement {
	j.Nonce = func(context.Context) string {
		return nonce
	}
	return j
}

// WithNonceFrom sets the value of the nonce attribute of the script element to the value returned by the given function.
func (j JSONScriptElement) WithNonceFrom(f func(context.Context) string) JSONScriptElement {
	j.Nonce = f
	return j
}

type JSONScriptElement struct {
	// ID of the element in the DOM.
	ID string
	// Type of the script element, defaults to "application/json".
	Type string
	// Data that will be encoded as JSON.
	Data any
	// Nonce is a function that returns a CSP nonce.
	// Defaults to CSPNonceFromContext.
	// See https://content-security-policy.com/nonce for more information.
	Nonce func(ctx context.Context) string
}

func (j JSONScriptElement) Render(ctx context.Context, w io.Writer) (err error) {
	if _, err = io.WriteString(w, "<script"); err != nil {
		return err
	}
	if j.ID != "" {
		if _, err = fmt.Fprintf(w, " id=\"%s\"", EscapeString(j.ID)); err != nil {
			return err
		}
	}
	if j.Type != "" {
		if _, err = fmt.Fprintf(w, " type=\"%s\"", EscapeString(j.Type)); err != nil {
			return err
		}
	}
	if nonce := j.Nonce(ctx); nonce != "" {
		if _, err = fmt.Fprintf(w, " nonce=\"%s\"", EscapeString(nonce)); err != nil {
			return err
		}
	}
	if _, err = io.WriteString(w, ">"); err != nil {
		return err
	}
	if err = json.NewEncoder(w).Encode(j.Data); err != nil {
		return err
	}
	if _, err = io.WriteString(w, "</script>"); err != nil {
		return err
	}
	return nil
}