hugo

Unnamed repository; edit this file 'description' to name the repository.

git clone git://git.shimmy1996.com/hugo.git
commit 35abce27cabee43cc751db55a75b927f26275833
parent 8914fe7ed7e7e55e07be32564159310c90e2dbd4
Author: Vincent Fiduccia <vincent@rancher.com>
Date:   Sat,  1 Jun 2019 23:56:19 -0700

Add safety barrier between concatenated javascript resources

Diffstat:
Mhugolib/resource_chain_test.go | 18++++++++++++++++++
Mresources/resource_factories/bundler/bundler.go | 25++++++++++++++++++++++---
2 files changed, 40 insertions(+), 3 deletions(-)
diff --git a/hugolib/resource_chain_test.go b/hugolib/resource_chain_test.go
@@ -244,6 +244,13 @@ T2: Content: {{ $combinedText.Content }}|{{ $combinedText.RelPermalink }}
 {{ $css := "body { color: blue; }" | resources.FromString "styles.css" }}
 {{ $minified := resources.Get "css/styles1.css" | minify }}
 {{ slice $css $minified | resources.Concat "bundle/mixed.css" }} 
+{{/* https://github.com/gohugoio/hugo/issues/5403 */}}
+{{ $d := "function D {} // A comment" | resources.FromString "d.js"}}
+{{ $e := "(function E {})" | resources.FromString "e.js"}}
+{{ $f := "(function F {})()" | resources.FromString "f.js"}}
+{{ $jsResources := .Resources.Match "*.js" }}
+{{ $combinedJs := slice $d $e $f | resources.Concat "bundle/concatjs.js" }}
+T3: Content: {{ $combinedJs.Content }}|{{ $combinedJs.RelPermalink }}
 `)
 		}, func(b *sitesBuilder) {
 			b.AssertFileContent("public/index.html", `T1: Content: ABC|RelPermalink: /bundle/concat.txt|Permalink: http://example.com/bundle/concat.txt|MediaType: text/plain`)
@@ -251,6 +258,17 @@ T2: Content: {{ $combinedText.Content }}|{{ $combinedText.RelPermalink }}
 
 			b.AssertFileContent("public/index.html", `T2: Content: t1t|t2t|`)
 			b.AssertFileContent("public/bundle/concattxt.txt", "t1t|t2t|")
+
+			b.AssertFileContent("public/index.html", `T3: Content: function D {} // A comment
+;
+(function E {})
+;
+(function F {})()|`)
+			b.AssertFileContent("public/bundle/concatjs.js", `function D {} // A comment
+;
+(function E {})
+;
+(function F {})()`)
 		}},
 		{"fromstring", func() bool { return true }, func(b *sitesBuilder) {
 			b.WithTemplates("home.html", `
diff --git a/resources/resource_factories/bundler/bundler.go b/resources/resource_factories/bundler/bundler.go
@@ -15,6 +15,7 @@
 package bundler
 
 import (
+	"bytes"
 	"fmt"
 	"io"
 	"path/filepath"
@@ -92,12 +93,30 @@ func (c *Client) Concat(targetPath string, r resource.Resources) (resource.Resou
 					}
 					return nil, err
 				}
+
 				rcsources = append(rcsources, rc)
 			}
 
-			readers := make([]io.Reader, len(rcsources))
-			for i := 0; i < len(rcsources); i++ {
-				readers[i] = rcsources[i]
+			var readers []io.Reader
+
+			// Arbitrary JavaScript files require a barrier between them to be safely concatenated together.
+			// Without this, the last line of one file can affect the first line of the next file and change how both files are interpreted.
+			if resolvedm.MainType == media.JavascriptType.MainType && resolvedm.SubType == media.JavascriptType.SubType {
+				readers = make([]io.Reader, 2*len(rcsources)-1)
+				j := 0
+				for i := 0; i < len(rcsources); i++ {
+					if i > 0 {
+						readers[j] = bytes.NewBufferString("\n;\n")
+						j++
+					}
+					readers[j] = rcsources[i]
+					j++
+				}
+			} else {
+				readers = make([]io.Reader, len(rcsources))
+				for i := 0; i < len(rcsources); i++ {
+					readers[i] = rcsources[i]
+				}
 			}
 
 			mr := io.MultiReader(readers...)