mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-27 22:09:53 +02:00
pipes: Add external source map support to js.Build and Babel
Fixes #8132
This commit is contained in:
@@ -16,7 +16,11 @@ package babel
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/cli/safeexec"
|
||||
@@ -43,8 +47,10 @@ type Options struct {
|
||||
Compact *bool
|
||||
Verbose bool
|
||||
NoBabelrc bool
|
||||
SourceMap string
|
||||
}
|
||||
|
||||
// DecodeOptions decodes options to and generates command flags
|
||||
func DecodeOptions(m map[string]interface{}) (opts Options, err error) {
|
||||
if m == nil {
|
||||
return
|
||||
@@ -56,6 +62,14 @@ func DecodeOptions(m map[string]interface{}) (opts Options, err error) {
|
||||
func (opts Options) toArgs() []string {
|
||||
var args []string
|
||||
|
||||
// external is not a known constant on the babel command line
|
||||
// .sourceMaps must be a boolean, "inline", "both", or undefined
|
||||
switch opts.SourceMap {
|
||||
case "external":
|
||||
args = append(args, "--source-maps")
|
||||
case "inline":
|
||||
args = append(args, "--source-maps=inline")
|
||||
}
|
||||
if opts.Minified {
|
||||
args = append(args, "--minified")
|
||||
}
|
||||
@@ -141,6 +155,8 @@ func (t *babelTransformation) Transform(ctx *resources.ResourceTransformationCtx
|
||||
}
|
||||
}
|
||||
|
||||
ctx.ReplaceOutPathExtension(".js")
|
||||
|
||||
var cmdArgs []string
|
||||
|
||||
if configFile != "" {
|
||||
@@ -153,13 +169,24 @@ func (t *babelTransformation) Transform(ctx *resources.ResourceTransformationCtx
|
||||
}
|
||||
cmdArgs = append(cmdArgs, "--filename="+ctx.SourcePath)
|
||||
|
||||
// Create compile into a real temp file:
|
||||
// 1. separate stdout/stderr messages from babel (https://github.com/gohugoio/hugo/issues/8136)
|
||||
// 2. allow generation and retrieval of external source map.
|
||||
compileOutput, err := ioutil.TempFile("", "compileOut-*.js")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmdArgs = append(cmdArgs, "--out-file="+compileOutput.Name())
|
||||
defer os.Remove(compileOutput.Name())
|
||||
|
||||
cmd, err := hexec.SafeCommand(binary, cmdArgs...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Stdout = ctx.To
|
||||
cmd.Stderr = io.MultiWriter(infoW, &errBuf)
|
||||
cmd.Stdout = cmd.Stderr
|
||||
cmd.Env = hugo.GetExecEnviron(t.rs.WorkingDir, t.rs.Cfg, t.rs.BaseFs.Assets.Fs)
|
||||
|
||||
stdin, err := cmd.StdinPipe()
|
||||
@@ -177,6 +204,28 @@ func (t *babelTransformation) Transform(ctx *resources.ResourceTransformationCtx
|
||||
return errors.Wrap(err, errBuf.String())
|
||||
}
|
||||
|
||||
content, err := ioutil.ReadAll(compileOutput)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mapFile := compileOutput.Name() + ".map"
|
||||
if _, err := os.Stat(mapFile); err == nil {
|
||||
defer os.Remove(mapFile)
|
||||
sourceMap, err := ioutil.ReadFile(mapFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = ctx.PublishSourceMap(string(sourceMap)); err != nil {
|
||||
return err
|
||||
}
|
||||
targetPath := path.Base(ctx.OutPath) + ".map"
|
||||
re := regexp.MustCompile(`//# sourceMappingURL=.*\n?`)
|
||||
content = []byte(re.ReplaceAllString(string(content), "//# sourceMappingURL="+targetPath+"\n"))
|
||||
}
|
||||
|
||||
ctx.To.Write(content)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -18,6 +18,8 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/afero"
|
||||
@@ -92,6 +94,14 @@ func (t *buildTransformation) Transform(ctx *resources.ResourceTransformationCtx
|
||||
return err
|
||||
}
|
||||
|
||||
if buildOptions.Sourcemap == api.SourceMapExternal && buildOptions.Outdir == "" {
|
||||
buildOptions.Outdir, err = ioutil.TempDir(os.TempDir(), "compileOutput")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove(buildOptions.Outdir)
|
||||
}
|
||||
|
||||
result := api.Build(buildOptions)
|
||||
|
||||
if len(result.Errors) > 0 {
|
||||
@@ -145,7 +155,25 @@ func (t *buildTransformation) Transform(ctx *resources.ResourceTransformationCtx
|
||||
return errors[0]
|
||||
}
|
||||
|
||||
ctx.To.Write(result.OutputFiles[0].Contents)
|
||||
if buildOptions.Sourcemap == api.SourceMapExternal {
|
||||
content := string(result.OutputFiles[1].Contents)
|
||||
symPath := path.Base(ctx.OutPath) + ".map"
|
||||
re := regexp.MustCompile(`//# sourceMappingURL=.*\n?`)
|
||||
content = re.ReplaceAllString(content, "//# sourceMappingURL="+symPath+"\n")
|
||||
|
||||
if err = ctx.PublishSourceMap(string(result.OutputFiles[0].Contents)); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := ctx.To.Write([]byte(content))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
_, err := ctx.To.Write(result.OutputFiles[0].Contents)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -338,6 +338,8 @@ func toBuildOptions(opts Options) (buildOptions api.BuildOptions, err error) {
|
||||
switch opts.SourceMap {
|
||||
case "inline":
|
||||
sourceMap = api.SourceMapInline
|
||||
case "external":
|
||||
sourceMap = api.SourceMapExternal
|
||||
case "":
|
||||
sourceMap = api.SourceMapNone
|
||||
default:
|
||||
|
@@ -109,4 +109,22 @@ func TestToBuildOptions(t *testing.T) {
|
||||
Loader: api.LoaderJS,
|
||||
},
|
||||
})
|
||||
|
||||
opts, err = toBuildOptions(Options{
|
||||
Target: "es2018", Format: "cjs", Minify: true, mediaType: media.JavascriptType,
|
||||
SourceMap: "external",
|
||||
})
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(opts, qt.DeepEquals, api.BuildOptions{
|
||||
Bundle: true,
|
||||
Target: api.ES2018,
|
||||
Format: api.FormatCommonJS,
|
||||
MinifyIdentifiers: true,
|
||||
MinifySyntax: true,
|
||||
MinifyWhitespace: true,
|
||||
Sourcemap: api.SourceMapExternal,
|
||||
Stdin: &api.StdinOptions{
|
||||
Loader: api.LoaderJS,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user