diff --git a/kibble/api/translations.go b/kibble/api/translations.go index df70400..f5b316d 100644 --- a/kibble/api/translations.go +++ b/kibble/api/translations.go @@ -44,7 +44,7 @@ func LoadAllTranslations(cfg *models.Config, site *models.Site) error { site.Translations[formatPathLocale(code)] = wholeLanguage } - log.Infof("Translations Recieved and Parsed") + log.Infof("Translations received and parsed") return nil } diff --git a/kibble/render/live_reload.go b/kibble/render/live_reload.go index 5d5343b..2db02fe 100644 --- a/kibble/render/live_reload.go +++ b/kibble/render/live_reload.go @@ -31,7 +31,7 @@ import ( fsnotify "gopkg.in/fsnotify/fsnotify.v1" ) -var embed = ` +var liveReloadEmbed = ` ` +var kibbleErrorMessage = ` +
+ Kibble errors +

This may prevent the site from working properly. Check terminal output for details

+

+ + + + +` + // LiveReload - type LiveReload struct { lastModified time.Time @@ -73,9 +122,9 @@ type LiveReload struct { // intercepts all write calls so as to append the live reload script type WrapperResponseWriter struct { http.ResponseWriter - status int - buf bytes.Buffer - prefixBuf bytes.Buffer + status int + buf bytes.Buffer + htmlToInject bytes.Buffer } // NewWrapperResponseWriter - create a new response writer @@ -94,25 +143,50 @@ func (w *WrapperResponseWriter) Write(p []byte) (n int, err error) { return len(p), nil } -// PrefixWithLogs - write the logs to the head of the page -func (w *WrapperResponseWriter) PrefixWithLogs(logs []string) { - if len(logs) == 0 { - return - } - - w.prefixBuf.Write([]byte("
")) - for _, s := range logs { - w.prefixBuf.Write([]byte(fmt.Sprintf("
%s
", s))) - } - w.prefixBuf.Write([]byte("
")) +func (w *WrapperResponseWriter) AddHtmlInject(html string) { + w.htmlToInject.WriteString(html) } // Done - called when are ready to return a result -func (w *WrapperResponseWriter) Done() (n int, err error) { - w.Header().Set("Content-Length", strconv.Itoa(w.buf.Len()+w.prefixBuf.Len())) +func (w *WrapperResponseWriter) Done() (err error) { + if w.htmlToInject.Len() > 0 { + responseBytes := w.buf.Bytes() + + // Find the end of the HTML body to inject our stuff. This is a little + // bit flaky as it assumes "sensible" html style on the body closing tag + endOfBodyIndex := bytes.LastIndex(responseBytes, []byte("")) + if endOfBodyIndex >= 0 { + chunks := [][]byte{ + responseBytes[0:endOfBodyIndex], + w.htmlToInject.Bytes(), + responseBytes[endOfBodyIndex:], + } + + length := 0 + for _, chunk := range chunks { + length += len(chunk) + } + + w.Header().Set("Content-Length", strconv.Itoa(length)) + w.ResponseWriter.WriteHeader(w.status) + + for _, chunk := range chunks { + if _, err = w.ResponseWriter.Write(chunk); err != nil { + return err + } + } + + return nil + } + + // If no end of body can be found, don't inject anything. It might be a + // partial, or not a valid HTML doc. + } + + w.Header().Set("Content-Length", strconv.Itoa(w.buf.Len())) w.ResponseWriter.WriteHeader(w.status) - _, _ = w.ResponseWriter.Write(w.prefixBuf.Bytes()) - return w.ResponseWriter.Write(w.buf.Bytes()) + _, err = w.ResponseWriter.Write(w.buf.Bytes()) + return err } // WriteHeader - wrap the write header @@ -132,15 +206,19 @@ func (live *LiveReload) GetMiddleware(next http.Handler) http.Handler { strings.HasSuffix(r.RequestURI, ".html") { if ww.Status() == 200 { - ww.PrefixWithLogs(live.logReader.Logs()) + if len(live.logReader.Logs()) > 0 { + ww.AddHtmlInject(kibbleErrorMessage) + } if live.reloadBrowserOnFileChange { - _, _ = ww.Write([]byte(embed)) + ww.AddHtmlInject(liveReloadEmbed) } } } - _, _ = ww.Done() + if err := ww.Done(); err != nil { + panic(err) + } }) }