Skip to content

Commit ba200ef

Browse files
Encode static files to avoid problems with special characters
Serve figures in server mode for the same reason. It is also a good reference example if people want to build on top
1 parent b83a081 commit ba200ef

File tree

2 files changed

+59
-11
lines changed

2 files changed

+59
-11
lines changed

examples/bar.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<body>
66
<div id="plot"></div>
77
<script>
8-
data = JSON.parse('{"data":[{"type":"bar","base":null,"hoverinfo":null,"hovertemplate":null,"hovertext":null,"meta":null,"offset":null,"text":null,"textposition":null,"texttemplate":null,"width":null,"x":[1,2,3],"y":[1,2,3]}],"layout":{"meta":null,"title":{"text":"A Figure Specified By Go Struct"}}}')
8+
data = JSON.parse(atob('eyJkYXRhIjpbeyJ0eXBlIjoiYmFyIiwiYmFzZSI6bnVsbCwiaG92ZXJpbmZvIjpudWxsLCJob3ZlcnRlbXBsYXRlIjpudWxsLCJob3ZlcnRleHQiOm51bGwsIm1ldGEiOm51bGwsIm9mZnNldCI6bnVsbCwidGV4dCI6bnVsbCwidGV4dHBvc2l0aW9uIjpudWxsLCJ0ZXh0dGVtcGxhdGUiOm51bGwsIndpZHRoIjpudWxsLCJ4IjpbMSwyLDNdLCJ5IjpbMSwyLDNdfV0sImxheW91dCI6eyJtZXRhIjpudWxsLCJ0aXRsZSI6eyJ0ZXh0IjoiQSBGaWd1cmUgJ1NwZWNpZmllZCcgQnkgR28gU3RydWN0In19fQ=='))
99
Plotly.newPlot('plot', data);
1010
</script>
1111
</body>

pkg/offline/plot.go

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package offline
22

33
import (
44
"bytes"
5+
"encoding/base64"
56
"encoding/json"
67
"log"
78
"net/http"
@@ -34,17 +35,18 @@ func figToBuffer(fig types.Fig) *bytes.Buffer {
3435
if err != nil {
3536
panic(err)
3637
}
37-
tmpl, err := template.New("plotly").Parse(baseHtml)
38+
tmpl, err := template.New("plotly").Parse(singleFileHTML)
3839
if err != nil {
3940
panic(err)
4041
}
4142
buf := &bytes.Buffer{}
4243
data := struct {
43-
Version types.Version
44-
Content string
44+
Version types.Version
45+
B64Content string
4546
}{
4647
Version: fig.Info(),
47-
Content: string(figBytes),
48+
// Encode to avoid problems with special characters
49+
B64Content: base64.StdEncoding.EncodeToString(figBytes),
4850
}
4951

5052
err = tmpl.Execute(buf, data)
@@ -66,12 +68,18 @@ func Serve(fig types.Fig, opt ...Options) {
6668
Handler: mux,
6769
Addr: opts.Addr,
6870
}
69-
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
70-
buf := figToBuffer(fig)
71-
buf.WriteTo(w)
71+
72+
mux.HandleFunc("/content", func(w http.ResponseWriter, r *http.Request) {
73+
err := json.NewEncoder(w).Encode(fig)
74+
if err != nil {
75+
log.Printf("Error rendering template, %s", err)
76+
w.WriteHeader(http.StatusInternalServerError)
77+
}
7278
})
7379

74-
log.Print("Starting server")
80+
mux.HandleFunc("/", webPage(fig, "/content"))
81+
82+
log.Printf("Starting server at %s", srv.Addr)
7583
if err := srv.ListenAndServe(); err != nil {
7684
log.Print(err)
7785
}
@@ -88,15 +96,55 @@ func computeOptions(def Options, opt ...Options) Options {
8896
return def
8997
}
9098

91-
var baseHtml = `
99+
var singleFileHTML = `
92100
<head>
93101
<script src="{{ .Version.Cdn }}"></script>
94102
</head>
95103
<body>
96104
<div id="plot"></div>
97105
<script>
98-
data = JSON.parse('{{ .Content }}')
106+
data = JSON.parse(atob('{{ .B64Content }}'))
99107
Plotly.newPlot('plot', data);
100108
</script>
101109
</body>
102110
`
111+
112+
type serverHTMLdata struct {
113+
Version types.Version
114+
ContentURL string
115+
}
116+
117+
func webPage(fig types.Fig, contentURL string) func(w http.ResponseWriter, r *http.Request) {
118+
return func(w http.ResponseWriter, r *http.Request) {
119+
tmpl := template.Must(template.New("server").Parse(serverHTML))
120+
data := serverHTMLdata{
121+
Version: fig.Info(),
122+
ContentURL: contentURL,
123+
}
124+
err := tmpl.Execute(w, data)
125+
if err != nil {
126+
log.Printf("Error rendering template, %s", err)
127+
w.WriteHeader(http.StatusInternalServerError)
128+
return
129+
}
130+
}
131+
}
132+
133+
var serverHTML = `
134+
<head>
135+
<script src="{{ .Version.Cdn }}"></script>
136+
</head>
137+
<body>
138+
<div id="plot"></div>
139+
<script>
140+
const url = '{{ .ContentURL }}'
141+
fetch(url)
142+
.then(response => response.json()) // Parse the JSON data from the response
143+
.then(data => {
144+
// Use the fetched data to create the Plotly plot
145+
Plotly.newPlot('plot', data);
146+
})
147+
.catch(error => console.error('Error fetching data:', error));
148+
</script>
149+
</body>
150+
`

0 commit comments

Comments
 (0)