Repository: gohugoio/hugo (language: go)

Issue:
JS destructuring assignment minification bug
Hi, I noticed that Hugo has a problem minifying my javascript. This is my pipeline:

``` go template
{{ $jspath := "js/main.ts" }}
{{- $jscratch := newScratch -}}

{{ if eq hugo.Environment "production" -}}
  {{ $jscratch.Set "mainjs" (resources.Get $jspath | js.Build | minify | fingerprint) -}}
{{- else -}}
  {{ $jscratch.Set "mainjs" (resources.Get $jspath | js.Build | fingerprint) -}}
{{- end -}}

{{ $mainjs := $jscratch.Get "mainjs" -}}

<script src="{{ $mainjs.RelPermalink }}" integrity="{{ $mainjs.Data.Integrity }}" defer></script>
```

It worked fine in development using `hugo server` but when I built for production using `hugo --minify` I would get an error about an unexpected colon, which means the problem is with Hugo's built-in minification function

I traced it to one of Splide's (v3.2.5) source files which I'm importing like so:

``` typescript
import Splide from '@splidejs/splide';
```

The source file that Hugo's minifier is having an issue with (after being bundled by esbuild) is `@splidejs/splide/src/js/utils/math/math/math.ts`, which contains:

``` typescript
export const { min, max, floor, ceil, abs } = Math;
```

Apparently, after running through esbuild and Hugo's minifier it results in the following summarized code, which is invalid:

``` javascript
var S, O, az, H, g // These are declared with a ton of other variables
// . . . Many characters later . . .
{min:S,max:O,floor:az,ceil:H,abs:g}=Math; // And this where the error occurs.
```

I was able to get around this by letting esbuild perform the minification instead (which I didn't know you could do at the time of discovering this error):

``` go template
  {{ $jscratch.Set "mainjs" (resources.Get $jspath | js.Build (dict "minify" true) | fingerprint) -}}
```

Which is probably the right way to minify my JS in this situation, but I decided to report this as a bug anyway because Hugo's minify tool is taking valid JS from esbuild and returning invalid JS.

### What version of Hugo are you using (`hugo version`)?

```console
$ hugo version
hugo v0.88.1-5BC54738+extended windows/amd64 BuildDate=2021-09-04T09:39:19Z VendorInfo=gohugoio
```

### Does this issue reproduce with the latest release?
Yes.



Discussion / hints:
Please generate an un-minified JS file for testing. The result of:

```
{{ $jscratch.Set "mainjs" (resources.Get $jspath | js.Build) }}
```

Then post somewhere. This is probably upstream, and we need the "before" state.
> 
> 
> Please generate an un-minified JS file for testing. The result of:
> 
> ```
> {{ $jscratch.Set "mainjs" (resources.Get $jspath | js.Build) }}
> ```

https://gist.github.com/apokaliptis/a715f5113bfba7dc4d0cd5b73b5f454f


Here's a minimal failing example:

```js
var a = 1;
function f() {
  return 1;
}
var { min, max } = Math;
function g() {
  return 2;
}
```

<https://github.com/tdewolff/minify> (BAD)

```js
var a=1,min,max;function f(){return 1}{min,max}=Math;function g(){return 2}
```

<https://jscompress.com> (GOOD)

```js
var a=1;function f(){return 1}var{min:min,max:max}=Math;function g(){return 2}
```
Upstream https://github.com/tdewolff/minify/issues/445
It's a bug, alright. That said, I would recommend that you use the minify option in `js.Build` instead, e.g.

```html
{{ $params := (dict "is_production" hugo.IsProduction ) }}
{{ $sourceMap := cond hugo.IsProduction "" "inline" }}
{{ $opts := dict "sourceMap" $sourceMap "minify" hugo.IsProduction "target" "es2018" "params" $params }}
{{ $js = $js | js.Build $opts }}
```

Fix patch:
diff --git a/go.mod b/go.mod
index 7152c5b24fa..39bed60d25c 100644
--- a/go.mod
+++ b/go.mod
@@ -55,7 +55,7 @@ require (
 	github.com/spf13/jwalterweatherman v1.1.0
 	github.com/spf13/pflag v1.0.5
 	github.com/spf13/viper v1.10.1
-	github.com/tdewolff/minify/v2 v2.9.22
+	github.com/tdewolff/minify/v2 v2.9.29
 	github.com/yuin/goldmark v1.4.4
 	github.com/yuin/goldmark-highlighting v0.0.0-20200307114337-60d527fdb691
 	gocloud.dev v0.20.0
diff --git a/go.sum b/go.sum
index 57d1645f8c1..ca1c58318af 100644
--- a/go.sum
+++ b/go.sum
@@ -602,10 +602,10 @@ github.com/stretchr/testify v1.7.1-0.20210427113832-6241f9ab9942 h1:t0lM6y/M5IiU
 github.com/stretchr/testify v1.7.1-0.20210427113832-6241f9ab9942/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
-github.com/tdewolff/minify/v2 v2.9.22 h1:PlmaAakaJHdMMdTTwjjsuSwIxKqWPTlvjTj6a/g/ILU=
-github.com/tdewolff/minify/v2 v2.9.22/go.mod h1:dNlaFdXaIxgSXh3UFASqjTY0/xjpDkkCsYHA1NCGnmQ=
-github.com/tdewolff/parse/v2 v2.5.21 h1:s/OLsVxxmQUlbFtPODDVHA836qchgmoxjEsk/cUZl48=
-github.com/tdewolff/parse/v2 v2.5.21/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
+github.com/tdewolff/minify/v2 v2.9.29 h1:QMVJaCJzWL0mXS33cX792YD074xz4lOhkyBS8hAzYAY=
+github.com/tdewolff/minify/v2 v2.9.29/go.mod h1:6XAjcHM46pFcRE0eztigFPm0Q+Cxsw8YhEWT+rDkcZM=
+github.com/tdewolff/parse/v2 v2.5.27 h1:PL3LzzXaOpmdrknnOlIeO2muIBHAwiKp6TxN1RbU5gI=
+github.com/tdewolff/parse/v2 v2.5.27/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
 github.com/tdewolff/test v1.0.6 h1:76mzYJQ83Op284kMT+63iCNCI7NEERsIN8dLM+RiKr4=
 github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
 github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=


Test patch:
diff --git a/hugolib/resource_chain_test.go b/hugolib/resource_chain_test.go
index 8b17b01a484..b45f956bbf6 100644
--- a/hugolib/resource_chain_test.go
+++ b/hugolib/resource_chain_test.go
@@ -699,8 +699,8 @@ Min HTML Remote: {{ ( resources.GetRemote "%[1]s/mydata/html1.html" | resources.
 		}, func(b *sitesBuilder) {
 			b.AssertFileContent("public/index.html", `Min CSS: h1{font-style:bold}`)
 			b.AssertFileContent("public/index.html", `Min CSS Remote: h1{font-style:bold}`)
-			b.AssertFileContent("public/index.html", `Min JS: var x;x=5,document.getElementById(&#34;demo&#34;).innerHTML=x*10`)
-			b.AssertFileContent("public/index.html", `Min JS Remote: var x;x=5,document.getElementById(&#34;demo&#34;).innerHTML=x*10`)
+			b.AssertFileContent("public/index.html", `Min JS: var x=5;document.getElementById(&#34;demo&#34;).innerHTML=x*10`)
+			b.AssertFileContent("public/index.html", `Min JS Remote: var x=5;document.getElementById(&#34;demo&#34;).innerHTML=x*10`)
 			b.AssertFileContent("public/index.html", `Min JSON: {"employees":[{"firstName":"John","lastName":"Doe"},{"firstName":"Anna","lastName":"Smith"},{"firstName":"Peter","lastName":"Jones"}]}`)
 			b.AssertFileContent("public/index.html", `Min JSON Remote: {"employees":[{"firstName":"John","lastName":"Doe"},{"firstName":"Anna","lastName":"Smith"},{"firstName":"Peter","lastName":"Jones"}]}`)
 			b.AssertFileContent("public/index.html", `Min XML: <hello><world>Hugo Rocks!</<world></hello>`)