1
0
mirror of https://github.com/danog/gojekyll.git synced 2025-01-23 00:01:14 +01:00

Inject livereload tag

This commit is contained in:
Oliver Steele 2017-06-17 14:30:38 -04:00
parent 0a3b31cbf7
commit a74668ebb9

View File

@ -1,12 +1,15 @@
package gojekyll package gojekyll
import ( import (
"bytes"
"fmt" "fmt"
"io"
"log" "log"
"mime" "mime"
"net/http" "net/http"
"path" "path"
"path/filepath" "path/filepath"
"strings"
"sync" "sync"
"time" "time"
@ -41,14 +44,15 @@ func (s *Server) handler(rw http.ResponseWriter, r *http.Request) {
site := s.Site site := s.Site
urlpath := r.URL.Path urlpath := r.URL.Path
mimeType := mime.TypeByExtension(path.Ext(urlpath)) ext := path.Ext(urlpath)
if mimeType != "" { if ext == "" {
rw.Header().Set("Content-Type", mimeType) ext = ".html"
} }
p, found := site.PageForURL(urlpath) p, found := site.PageForURL(urlpath)
if !found { if !found {
rw.WriteHeader(http.StatusNotFound) rw.WriteHeader(http.StatusNotFound)
ext = ".html"
p, found = site.Paths["404.html"] p, found = site.Paths["404.html"]
} }
if !found { if !found {
@ -56,15 +60,47 @@ func (s *Server) handler(rw http.ResponseWriter, r *http.Request) {
return return
} }
err := p.Write(rw) mimeType := mime.TypeByExtension(ext)
if mimeType != "" {
rw.Header().Set("Content-Type", mimeType)
}
var w io.Writer = rw
if strings.HasPrefix(mimeType, "text/html;") {
w = scriptTagInjector{w}
}
err := p.Write(w)
if err != nil { if err != nil {
fmt.Printf("Error rendering %s: %s", urlpath, err) fmt.Printf("Error rendering %s: %s", urlpath, err)
} }
} }
type scriptTagInjector struct {
w io.Writer
}
var liveReloadScriptTag = []byte(`<script src="http://localhost:35729/livereload.js"></script>`)
var liveReloadSearchBytes = []byte(`</head>`)
var liveReloadReplacementBytes = append(liveReloadScriptTag, liveReloadSearchBytes...)
// Write injects a livereload script tag at the end of the HTML head, if present,
// else at the beginning of the document.
// It depends on the fact that dynamic page rendering makes a single Write call,
// so that it's guaranteed to find the marker within a single invocation argument.
// It doesn't parse HTML, so it could be spoofed but probably only intentionally.
func (i scriptTagInjector) Write(p []byte) (n int, err error) {
if !bytes.Contains(p, liveReloadSearchBytes) {
p = bytes.Replace(p, []byte(liveReloadSearchBytes), []byte(liveReloadReplacementBytes), 1)
}
if !bytes.Contains(p, liveReloadSearchBytes) {
p = append(liveReloadScriptTag, p...)
}
return i.w.Write(p)
}
func (s *Server) syncReloadSite() { func (s *Server) syncReloadSite() {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
start := time.Now() start := time.Now()
fmt.Printf("%s Reloading site...", start.Format(time.Stamp)) fmt.Printf("%s Reloading site...", start.Format(time.Stamp))
if err := s.Site.Reload(); err != nil { if err := s.Site.Reload(); err != nil {