From 35abce27cabee43cc751db55a75b927f26275833 Mon Sep 17 00:00:00 2001 From: Vincent Fiduccia Date: Sat, 1 Jun 2019 23:56:19 -0700 Subject: [PATCH] Add safety barrier between concatenated javascript resources --- hugolib/resource_chain_test.go | 18 +++++++++++++ .../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 index 5a8ac22d7..8f55e112e 100644 --- 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 index ca0ccf86e..59810e347 100644 --- 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...)