summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--transform/absurl.go8
-rw-r--r--transform/absurlreplacer.go27
-rw-r--r--transform/chain.go73
-rw-r--r--transform/chain_test.go30
-rw-r--r--transform/livereloadinject.go17
5 files changed, 110 insertions, 45 deletions
diff --git a/transform/absurl.go b/transform/absurl.go
index 6fc62adcf..fa1d99306 100644
--- a/transform/absurl.go
+++ b/transform/absurl.go
@@ -17,8 +17,8 @@ func initAbsURLReplacer(baseURL string) {
func AbsURL(absURL string) (trs []link, err error) {
initAbsURLReplacer(absURL)
- trs = append(trs, func(content []byte) []byte {
- return ar.replaceInHTML(content)
+ trs = append(trs, func(rw ContentReWriter) {
+ ar.replaceInHTML(rw)
})
return
}
@@ -26,8 +26,8 @@ func AbsURL(absURL string) (trs []link, err error) {
func AbsURLInXML(absURL string) (trs []link, err error) {
initAbsURLReplacer(absURL)
- trs = append(trs, func(content []byte) []byte {
- return ar.replaceInXML(content)
+ trs = append(trs, func(rw ContentReWriter) {
+ ar.replaceInXML(rw)
})
return
}
diff --git a/transform/absurlreplacer.go b/transform/absurlreplacer.go
index 2f2a5bd53..66fdaf689 100644
--- a/transform/absurlreplacer.go
+++ b/transform/absurlreplacer.go
@@ -2,7 +2,7 @@ package transform
import (
"bytes"
- bp "github.com/spf13/hugo/bufferpool"
+ "io"
"net/url"
"strings"
"unicode/utf8"
@@ -33,7 +33,7 @@ type contentlexer struct {
state stateFunc
prefixLookup *prefixes
- b *bytes.Buffer
+ w io.Writer
}
type stateFunc func(*contentlexer) stateFunc
@@ -95,7 +95,7 @@ func (l *contentlexer) match(r rune) {
}
func (l *contentlexer) emit() {
- l.b.Write(l.content[l.start:l.pos])
+ l.w.Write(l.content[l.start:l.pos])
l.start = l.pos
}
@@ -134,7 +134,7 @@ func checkCandidate(l *contentlexer) {
l.emit()
}
l.pos += len(m.match)
- l.b.Write(m.replacement)
+ l.w.Write(m.replacement)
l.start = l.pos
return
@@ -159,7 +159,6 @@ func (l *contentlexer) replace() {
}
l.width = width
l.pos += l.width
-
if r == ' ' {
l.prefixLookup.ms = matchStateWhitespace
} else if l.prefixLookup.ms != matchStateNone {
@@ -177,18 +176,16 @@ func (l *contentlexer) replace() {
}
}
-func doReplace(content []byte, matchers []absURLMatcher) []byte {
- b := bp.GetBuffer()
- defer bp.PutBuffer(b)
+func doReplace(rw ContentReWriter, matchers []absURLMatcher) {
- lexer := &contentlexer{content: content,
- b: b,
+ lexer := &contentlexer{
+ content: rw.Content(),
+ w: rw,
prefixLookup: &prefixes{pr: mainPrefixRunes},
matchers: matchers}
lexer.replace()
- return b.Bytes()
}
type absURLReplacer struct {
@@ -229,10 +226,10 @@ func newAbsURLReplacer(baseURL string) *absURLReplacer {
}
-func (au *absURLReplacer) replaceInHTML(content []byte) []byte {
- return doReplace(content, au.htmlMatchers)
+func (au *absURLReplacer) replaceInHTML(rw ContentReWriter) {
+ doReplace(rw, au.htmlMatchers)
}
-func (au *absURLReplacer) replaceInXML(content []byte) []byte {
- return doReplace(content, au.xmlMatchers)
+func (au *absURLReplacer) replaceInXML(rw ContentReWriter) {
+ doReplace(rw, au.xmlMatchers)
}
diff --git a/transform/chain.go b/transform/chain.go
index c6e56960c..0edcb6971 100644
--- a/transform/chain.go
+++ b/transform/chain.go
@@ -1,12 +1,12 @@
package transform
import (
- "io"
-
+ "bytes"
bp "github.com/spf13/hugo/bufferpool"
+ "io"
)
-type trans func([]byte) []byte
+type trans func(rw ContentReWriter)
type link trans
@@ -20,17 +20,62 @@ func NewEmptyTransforms() []link {
return make([]link, 0, 20)
}
-func (c *chain) Apply(w io.Writer, r io.Reader) (err error) {
- buffer := bp.GetBuffer()
- defer bp.PutBuffer(buffer)
+// ContentReWriter is an interface that enables rotation
+// of pooled buffers in the transformer chain.
+type ContentReWriter interface {
+ Content() []byte
+ io.Writer
+}
+
+// Implements ContentReWriter
+// Content is read from the from-buffer,
+// and rewritten to to the to-buffer.
+type fromToBuffer struct {
+ from *bytes.Buffer
+ to *bytes.Buffer
+}
+
+func (ft fromToBuffer) Write(p []byte) (n int, err error) {
+ return ft.to.Write(p)
+}
+
+func (ft fromToBuffer) Content() []byte {
+ return ft.from.Bytes()
+}
- buffer.ReadFrom(r)
- b := buffer.Bytes()
- for _, tr := range *c {
- b = tr(b)
+func (c *chain) Apply(w io.Writer, r io.Reader) error {
+
+ b1 := bp.GetBuffer()
+ defer bp.PutBuffer(b1)
+
+ b1.ReadFrom(r)
+
+ if len(*c) == 0 {
+ b1.WriteTo(w)
+ return nil
}
- buffer.Reset()
- buffer.Write(b)
- buffer.WriteTo(w)
- return
+
+ b2 := bp.GetBuffer()
+ defer bp.PutBuffer(b2)
+
+ fb := &fromToBuffer{from: b1, to: b2}
+
+ for i, tr := range *c {
+ if i > 0 {
+ if fb.from == b1 {
+ fb.from = b2
+ fb.to = b1
+ fb.to.Reset()
+ } else {
+ fb.from = b1
+ fb.to = b2
+ fb.to.Reset()
+ }
+ }
+
+ tr(fb)
+ }
+
+ fb.to.WriteTo(w)
+ return nil
}
diff --git a/transform/chain_test.go b/transform/chain_test.go
index 8fa45f5a9..2477c3abf 100644
--- a/transform/chain_test.go
+++ b/transform/chain_test.go
@@ -2,6 +2,7 @@ package transform
import (
"bytes"
+ "github.com/spf13/hugo/helpers"
"strings"
"testing"
)
@@ -54,6 +55,35 @@ func TestChainZeroTransformers(t *testing.T) {
}
}
+func TestChaingMultipleTransformers(t *testing.T) {
+ f1 := func(rw ContentReWriter) {
+ rw.Write(bytes.Replace(rw.Content(), []byte("f1"), []byte("f1r"), -1))
+ }
+ f2 := func(rw ContentReWriter) {
+ rw.Write(bytes.Replace(rw.Content(), []byte("f2"), []byte("f2r"), -1))
+ }
+ f3 := func(rw ContentReWriter) {
+ rw.Write(bytes.Replace(rw.Content(), []byte("f3"), []byte("f3r"), -1))
+ }
+
+ f4 := func(rw ContentReWriter) {
+ rw.Write(bytes.Replace(rw.Content(), []byte("f4"), []byte("f4r"), -1))
+ }
+
+ tr := NewChain(f1, f2, f3, f4)
+
+ out := new(bytes.Buffer)
+ if err := tr.Apply(out, helpers.StringToReader("Test: f4 f3 f1 f2 f1 The End.")); err != nil {
+ t.Errorf("Multi transformer chain returned an error: %s", err)
+ }
+
+ expected := "Test: f4r f3r f1r f2r f1r The End."
+
+ if string(out.Bytes()) != expected {
+ t.Errorf("Expected %s got %s", expected, string(out.Bytes()))
+ }
+}
+
func BenchmarkAbsURL(b *testing.B) {
absURL, _ := AbsURL("http://base")
tr := NewChain(absURL...)
diff --git a/transform/livereloadinject.go b/transform/livereloadinject.go
index eb431f14a..bffedf040 100644
--- a/transform/livereloadinject.go
+++ b/transform/livereloadinject.go
@@ -2,29 +2,22 @@ package transform
import (
"bytes"
- jww "github.com/spf13/jwalterweatherman"
"github.com/spf13/viper"
)
-func LiveReloadInject(content []byte) (injected []byte) {
- defer func() {
- if r := recover(); r != nil {
- jww.ERROR.Println("Recovered in LiveReloadInject", r)
- injected = content
- }
- }()
+func LiveReloadInject(rw ContentReWriter) {
match := []byte("</body>")
port := viper.GetString("port")
replace := []byte(`<script>document.write('<script src="http://'
+ (location.host || 'localhost').split(':')[0]
+ ':` + port + `/livereload.js?mindelay=10"></'
+ 'script>')</script></body>`)
- newcontent := bytes.Replace(content, match, replace, -1)
+ newcontent := bytes.Replace(rw.Content(), match, replace, -1)
- if len(newcontent) == len(content) {
+ if len(newcontent) == len(rw.Content()) {
match := []byte("</BODY>")
- newcontent = bytes.Replace(content, match, replace, -1)
+ newcontent = bytes.Replace(rw.Content(), match, replace, -1)
}
- return newcontent
+ rw.Write(newcontent)
}