Skip to content

Commit

Permalink
fix #215: allow multiple dots in loader extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Jul 4, 2020
1 parent 74e3992 commit 9c1775e
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 6 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

* Allow multiple `.` characters in loader extensions ([#215](https://github.com/evanw/esbuild/issues/215))

You are now able to configure two loaders such that one is the suffix of the other. For example, you can now configure both `--loader:.txt=text` and `--loader:.base64.txt=base64`. The loader with the longer matching suffix will be used.

## 0.5.19

* Fix bug with TypeScript `typeof` operator ([#213](https://github.com/evanw/esbuild/issues/213))
Expand Down
24 changes: 19 additions & 5 deletions internal/bundler/bundler.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,8 @@ func parseFile(args parseArgs) {
args.options.Strict.ClassFields = true
}

// Get the file extension
extension := args.fs.Ext(args.absPath)

// Pick the loader based on the file extension
loader := args.options.ExtensionToLoader[extension]
loader := loaderFromFileExtension(args.options.ExtensionToLoader, args.fs.Base(args.absPath))

// Special-case reading from stdin
if stdin != nil {
Expand Down Expand Up @@ -169,7 +166,7 @@ func parseFile(args parseArgs) {
result.file.ignoreIfUnused = true

case config.LoaderDataURL:
mimeType := mime.TypeByExtension(extension)
mimeType := mime.TypeByExtension(args.fs.Ext(args.absPath))
if mimeType == "" {
mimeType = http.DetectContentType([]byte(source.Contents))
}
Expand Down Expand Up @@ -220,6 +217,23 @@ func parseFile(args parseArgs) {
args.results <- result
}

func loaderFromFileExtension(extensionToLoader map[string]config.Loader, base string) config.Loader {
// Pick the loader with the longest matching extension. So if there's an
// extension for ".css" and for ".module.css", we want to match the one for
// ".module.css" before the one for ".css".
for {
i := strings.IndexByte(base, '.')
if i == -1 {
break
}
if loader, ok := extensionToLoader[base[i:]]; ok {
return loader
}
base = base[i+1:]
}
return config.LoaderNone
}

// Identify the path by its lowercase absolute path name. This should
// hopefully avoid path case issues on Windows, which has case-insensitive
// file system paths.
Expand Down
37 changes: 37 additions & 0 deletions internal/bundler/bundler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2689,6 +2689,43 @@ console.log(require_test());
})
}

func TestRequireCustomExtensionPreferLongest(t *testing.T) {
expectBundled(t, bundled{
files: map[string]string{
"/entry.js": `
console.log(require('./test.txt'), require('./test.base64.txt'))
`,
"/test.txt": `test.txt`,
"/test.base64.txt": `test.base64.txt`,
},
entryPaths: []string{"/entry.js"},
options: config.Options{
IsBundling: true,
AbsOutputFile: "/out.js",
ExtensionToLoader: map[string]config.Loader{
".js": config.LoaderJS,
".txt": config.LoaderText,
".base64.txt": config.LoaderBase64,
},
},
expected: map[string]string{
"/out.js": `// /test.txt
var require_test = __commonJS((exports, module) => {
module.exports = "test.txt";
});
// /test.base64.txt
var require_test_base64 = __commonJS((exports, module) => {
module.exports = "dGVzdC5iYXNlNjQudHh0";
});
// /entry.js
console.log(require_test(), require_test_base64());
`,
},
})
}

func testAutoDetectMimeTypeFromExtension(t *testing.T) {
expectBundled(t, bundled{
files: map[string]string{
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/api_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func validateLoaders(log logging.Log, loaders map[string]Loader) map[string]conf
result := bundler.DefaultExtensionToLoaderMap()
if loaders != nil {
for ext, loader := range loaders {
if len(ext) < 2 || ext[0] != '.' || strings.ContainsRune(ext[1:], '.') {
if len(ext) < 2 || ext[0] != '.' || ext[len(ext)-1] == '.' {
log.AddError(nil, ast.Loc{}, fmt.Sprintf("Invalid file extension: %q", ext))
}
result[ext] = validateLoader(loader)
Expand Down

0 comments on commit 9c1775e

Please sign in to comment.