Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to pass '[ext]' template to output file name templates #1799

Merged
merged 4 commits into from Dec 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 4 additions & 3 deletions internal/bundler/bundler.go
Expand Up @@ -1812,21 +1812,22 @@ func (s *scanner) processScannedFiles() []scannerFile {

// Generate the input for the template
_, _, originalExt := logger.PlatformIndependentPathDirBaseExt(result.file.inputFile.Source.KeyPath.Text)
dir, base, ext := pathRelativeToOutbase(
dir, base := pathRelativeToOutbase(
&result.file.inputFile,
&s.options,
s.fs,
originalExt,
/* avoidIndex */ false,
/* customFilePath */ "",
)

// Apply the asset path template
templateExt := strings.TrimPrefix(originalExt, ".")
relPath := config.TemplateToString(config.SubstituteTemplate(s.options.AssetPathTemplate, config.PathPlaceholders{
Dir: &dir,
Name: &base,
Hash: &hash,
})) + ext
Ext: &templateExt,
})) + originalExt

// Optionally add metadata about the file
var jsonMetadataChunk string
Expand Down
32 changes: 32 additions & 0 deletions internal/bundler/bundler_default_test.go
Expand Up @@ -4981,3 +4981,35 @@ func TestEntryNamesNonPortableCharacter(t *testing.T) {
},
})
}

func TestEntryNamesChunkNamesExtPlaceholder(t *testing.T) {
loader_suite.expectBundled(t, bundled{
files: map[string]string{
"/src/entries/entry1.js": `import "../lib/shared.js"; import "./entry1.css"; console.log('entry1')`,
"/src/entries/entry2.js": `import "../lib/shared.js"; import "./entry2.css"; console.log('entry2')`,
"/src/entries/entry1.css": `a:after { content: "entry1" }`,
"/src/entries/entry2.css": `a:after { content: "entry2" }`,
"/src/lib/shared.js": `console.log('shared')`,
},
entryPaths: []string{
"/src/entries/entry1.js",
"/src/entries/entry2.js",
},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputBase: "/src",
AbsOutputDir: "/out",
CodeSplitting: true,
EntryPathTemplate: []config.PathTemplate{
{Data: "main/", Placeholder: config.ExtPlaceholder},
{Data: "/", Placeholder: config.NamePlaceholder},
{Data: "-", Placeholder: config.HashPlaceholder},
},
ChunkPathTemplate: []config.PathTemplate{
{Data: "common/", Placeholder: config.ExtPlaceholder},
{Data: "/", Placeholder: config.NamePlaceholder},
{Data: "-", Placeholder: config.HashPlaceholder},
},
},
})
}
30 changes: 30 additions & 0 deletions internal/bundler/bundler_loader_test.go
Expand Up @@ -469,6 +469,36 @@ func TestLoaderFileRelativePathAssetNamesJS(t *testing.T) {
})
}

func TestLoaderFileExtPathAssetNamesJS(t *testing.T) {
loader_suite.expectBundled(t, bundled{
files: map[string]string{
"/src/entries/entry.js": `
import x from '../images/image.png'
import y from '../uploads/file.txt'
console.log(x, y)
`,
"/src/images/image.png": "x",
"/src/uploads/file.txt": "y",
},
entryPaths: []string{"/src/entries/entry.js"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputBase: "/src",
AbsOutputDir: "/out",
AssetPathTemplate: []config.PathTemplate{
{Data: "", Placeholder: config.ExtPlaceholder},
{Data: "/", Placeholder: config.NamePlaceholder},
{Data: "-", Placeholder: config.HashPlaceholder},
},
ExtensionToLoader: map[string]config.Loader{
".js": config.LoaderJS,
".png": config.LoaderFile,
".txt": config.LoaderFile,
},
},
})
}

func TestLoaderFileRelativePathAssetNamesCSS(t *testing.T) {
loader_suite.expectBundled(t, bundled{
files: map[string]string{
Expand Down
10 changes: 5 additions & 5 deletions internal/bundler/linker.go
Expand Up @@ -610,12 +610,10 @@ func pathRelativeToOutbase(
inputFile *graph.InputFile,
options *config.Options,
fs fs.FS,
stdExt string,
avoidIndex bool,
customFilePath string,
) (relDir string, baseName string, baseExt string) {
) (relDir string, baseName string) {
relDir = "/"
baseExt = stdExt
absPath := inputFile.Source.KeyPath.Text

if customFilePath != "" {
Expand Down Expand Up @@ -3034,14 +3032,14 @@ func (c *linkerContext) computeChunks() []chunkInfo {
}
} else {
// Otherwise, derive the output path from the input path
dir, base, ext = pathRelativeToOutbase(
dir, base = pathRelativeToOutbase(
&c.graph.Files[chunk.sourceIndex].InputFile,
c.options,
c.fs,
stdExt,
!file.IsUserSpecifiedEntryPoint(),
c.graph.EntryPoints()[chunk.entryPointBit].OutputPath,
)
ext = stdExt
}
} else {
dir = "/"
Expand All @@ -3051,10 +3049,12 @@ func (c *linkerContext) computeChunks() []chunkInfo {
}

// Determine the output path template
templateExt := strings.TrimPrefix(ext, ".")
template = append(append(make([]config.PathTemplate, 0, len(template)+1), template...), config.PathTemplate{Data: ext})
chunk.finalTemplate = config.SubstituteTemplate(template, config.PathPlaceholders{
Dir: &dir,
Name: &base,
Ext: &templateExt,
})
}

Expand Down
46 changes: 46 additions & 0 deletions internal/bundler/snapshots/snapshots_loader.txt
Expand Up @@ -10,6 +10,36 @@ var require_test = __commonJS({
// entry.js
console.log(require_test());

================================================================================
TestEntryNamesChunkNamesExtPlaceholder
---------- /out/main/js/entry1-L7KI5G7A.js ----------
import "../../common/js/chunk-XHGYOYUR.js";

// src/entries/entry1.js
console.log("entry1");

---------- /out/main/js/entry2-KTHKWVT2.js ----------
import "../../common/js/chunk-XHGYOYUR.js";

// src/entries/entry2.js
console.log("entry2");

---------- /out/common/js/chunk-XHGYOYUR.js ----------
// src/lib/shared.js
console.log("shared");

---------- /out/main/css/entry1-3JZGIUSL.css ----------
/* src/entries/entry1.css */
a:after {
content: "entry1";
}

---------- /out/main/css/entry2-NXZBPPIA.css ----------
/* src/entries/entry2.css */
a:after {
content: "entry2";
}

================================================================================
TestJSXPreserveCapitalLetter
---------- /out.js ----------
Expand Down Expand Up @@ -116,6 +146,22 @@ var y_default = "./y-YE5AYNFB.txt";
var x_url = require_x();
console.log(x_url, y_default);

================================================================================
TestLoaderFileExtPathAssetNamesJS
---------- /out/png/image-LSAMBFUD.png ----------
x
---------- /out/txt/file-YE5AYNFB.txt ----------
y
---------- /out/entries/entry.js ----------
// src/images/image.png
var image_default = "../png/image-LSAMBFUD.png";

// src/uploads/file.txt
var file_default = "../txt/file-YE5AYNFB.txt";

// src/entries/entry.js
console.log(image_default, file_default);

================================================================================
TestLoaderFileMultipleNoCollision
---------- /dist/test-J7OMUXO3.txt ----------
Expand Down
9 changes: 9 additions & 0 deletions internal/config/config.go
Expand Up @@ -343,6 +343,10 @@ const (
// A hash of the contents of this file, and the contents and output paths of
// all dependencies (except for their hash placeholders)
HashPlaceholder

// The original extension of the file, or the name of the output file
// (e.g. "css", "svg", "png")
ExtPlaceholder
)

type PathTemplate struct {
Expand All @@ -354,6 +358,7 @@ type PathPlaceholders struct {
Dir *string
Name *string
Hash *string
Ext *string
}

func (placeholders PathPlaceholders) Get(placeholder PathPlaceholder) *string {
Expand All @@ -364,6 +369,8 @@ func (placeholders PathPlaceholders) Get(placeholder PathPlaceholder) *string {
return placeholders.Name
case HashPlaceholder:
return placeholders.Hash
case ExtPlaceholder:
return placeholders.Ext
}
return nil
}
Expand All @@ -383,6 +390,8 @@ func TemplateToString(template []PathTemplate) string {
sb.WriteString("[name]")
case HashPlaceholder:
sb.WriteString("[hash]")
case ExtPlaceholder:
sb.WriteString("[ext]")
}
}
return sb.String()
Expand Down
4 changes: 4 additions & 0 deletions pkg/api/api_impl.go
Expand Up @@ -65,6 +65,10 @@ func validatePathTemplate(template string) []config.PathTemplate {
placeholder = config.HashPlaceholder
search += len("[hash]")

case strings.HasPrefix(tail, "[ext]"):
placeholder = config.ExtPlaceholder
search += len("[ext]")

default:
// Skip past the "[" so we don't find it again
search++
Expand Down