summaryrefslogtreecommitdiffstats
path: root/transform
diff options
context:
space:
mode:
Diffstat (limited to 'transform')
-rw-r--r--transform/livereloadinject/livereloadinject.go53
-rw-r--r--transform/livereloadinject/livereloadinject_test.go42
2 files changed, 71 insertions, 24 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
diff --git a/transform/livereloadinject/livereloadinject_test.go b/transform/livereloadinject/livereloadinject_test.go
index 413ca7b43..4dd256bb0 100644
--- a/transform/livereloadinject/livereloadinject_test.go
+++ b/transform/livereloadinject/livereloadinject_test.go
@@ -15,27 +15,45 @@ package livereloadinject
import (
"bytes"
- "fmt"
"strings"
"testing"
+ qt "github.com/frankban/quicktest"
"github.com/gohugoio/hugo/transform"
)
func TestLiveReloadInject(t *testing.T) {
- doTestLiveReloadInject(t, "</body>")
- doTestLiveReloadInject(t, "</BODY>")
-}
+ c := qt.New(t)
-func doTestLiveReloadInject(t *testing.T, bodyEndTag string) {
- out := new(bytes.Buffer)
- in := strings.NewReader(bodyEndTag)
+ expectBase := `<script data-no-instant>document.write('<script src="/livereload.js?port=1313&mindelay=10&v=2"></' + 'script>')</script>`
+ apply := func(s string) string {
+ out := new(bytes.Buffer)
+ in := strings.NewReader(s)
- tr := transform.New(New(1313))
- tr.Apply(out, in)
+ tr := transform.New(New(1313))
+ tr.Apply(out, in)
- expected := fmt.Sprintf(`<script data-no-instant>document.write('<script src="/livereload.js?port=1313&mindelay=10&v=2"></' + 'script>')</script>%s`, bodyEndTag)
- if out.String() != expected {
- t.Errorf("Expected %s got %s", expected, out.String())
+ return out.String()
}
+
+ c.Run("Head lower", func(c *qt.C) {
+ c.Assert(apply("<html><head>foo"), qt.Equals, "<html><head>"+expectBase+"foo")
+ })
+
+ c.Run("Head upper", func(c *qt.C) {
+ c.Assert(apply("<html><HEAD>foo"), qt.Equals, "<html><HEAD>"+expectBase+"foo")
+ })
+
+ c.Run("Body lower", func(c *qt.C) {
+ c.Assert(apply("foo</body>"), qt.Equals, "foo"+expectBase+"</body>")
+ })
+
+ c.Run("Body upper", func(c *qt.C) {
+ c.Assert(apply("foo</BODY>"), qt.Equals, "foo"+expectBase+"</BODY>")
+ })
+
+ c.Run("No match", func(c *qt.C) {
+ c.Assert(apply("<h1>No match</h1>"), qt.Equals, "<h1>No match</h1>")
+ })
+
}