diff options
Diffstat (limited to 'transform/livereloadinject/livereloadinject.go')
-rw-r--r-- | transform/livereloadinject/livereloadinject.go | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/transform/livereloadinject/livereloadinject.go b/transform/livereloadinject/livereloadinject.go index bee40f25c..f34b4fb59 100644 --- a/transform/livereloadinject/livereloadinject.go +++ b/transform/livereloadinject/livereloadinject.go @@ -21,25 +21,54 @@ import ( "github.com/gohugoio/hugo/transform" ) +type tag struct { + markup []byte + appendScript bool +} + +var tags = []tag{ + tag{markup: []byte("<head>"), appendScript: true}, + tag{markup: []byte("<HEAD>"), appendScript: true}, + tag{markup: []byte("</body>")}, + tag{markup: []byte("</BODY>")}, +} + // New creates a function that can be used // to inject a script tag for the livereload JavaScript in a HTML document. func New(port int) transform.Transformer { return func(ft transform.FromTo) error { b := ft.From().Bytes() - endBodyTag := "</body>" - match := []byte(endBodyTag) - replaceTemplate := `<script data-no-instant>document.write('<script src="/livereload.js?port=%d&mindelay=10&v=2"></' + 'script>')</script>%s` - replace := []byte(fmt.Sprintf(replaceTemplate, port, endBodyTag)) - - newcontent := bytes.Replace(b, match, replace, 1) - if len(newcontent) == len(b) { - endBodyTag = "</BODY>" - replace := []byte(fmt.Sprintf(replaceTemplate, port, endBodyTag)) - match := []byte(endBodyTag) - newcontent = bytes.Replace(b, match, replace, 1) + var idx = -1 + var match tag + // We used to insert the livereload script right before the closing body. + // This does not work when combined with tools such as Turbolinks. + // So we try to inject the script as early as possible. + for _, t := range tags { + idx = bytes.Index(b, t.markup) + if idx != -1 { + match = t + break + } } - if _, err := ft.To().Write(newcontent); err != nil { + c := make([]byte, len(b)) + copy(c, b) + + if idx == -1 { + _, err := ft.To().Write(c) + return err + } + + script := []byte(fmt.Sprintf(`<script data-no-instant>document.write('<script src="/livereload.js?port=%d&mindelay=10&v=2"></' + 'script>')</script>`, port)) + + i := idx + if match.appendScript { + i += len(match.markup) + } + + c = append(c[:i], append(script, c[i:]...)...) + + if _, err := ft.To().Write(c); err != nil { helpers.DistinctWarnLog.Println("Failed to inject LiveReload script:", err) } return nil |