From b7c20571f26315bf6567578a4e1223a8f69918e3 Mon Sep 17 00:00:00 2001 From: Sebastiano Bellinzis Date: Tue, 17 Jun 2025 22:09:57 +0200 Subject: [PATCH] jsdelivr esm support --- README.md | 27 +++++++++++++++++++++++ client/jsdelivr/jsdelivr.go | 44 ++++++++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8e90c16..1d34af7 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,33 @@ results in generating: {"imports":{"htmx":"https://unpkg.com/browse/htmx.org@1.8.6/dist/htmx.min.js"}} ``` +### jsdelivr ESM imports can be fetched using the jsdelivr provider: + +```go + im := importmap. + NewDefaults(). + WithProvider(cdnjs.New()). + AssetsDir(path.Join("assets")). + WithPackages([]library.Package{ + { + Name: "htmx", + Version: "2.0.4", + Require: []library.Include{ + {File: "htmx.esm.min.js"}, + {File: "/ext/json-enc.js", As: "json-enc"}, + }, + },{ + Provider: jsdelivr.NewESM(), // + Name: "@simonwep/pickr", + Version: "1.9.1", + Require: []library.Include{ + {File: "/esm-bundle.js", As: "pickr"}, // + {File: "/dist/themes/nano.min.css", As: "nano.min.css"}, + }, + }, + }) +``` + ## Contributing Contributions are welcome! diff --git a/client/jsdelivr/jsdelivr.go b/client/jsdelivr/jsdelivr.go index 854182f..02575e9 100644 --- a/client/jsdelivr/jsdelivr.go +++ b/client/jsdelivr/jsdelivr.go @@ -19,6 +19,7 @@ type ( Client struct { apiBaseURL string cdnBaseURL string + esm bool } SearchResponse struct { @@ -58,9 +59,26 @@ func New() *Client { return &Client{ apiBaseURL: defaultApiBaseURL, cdnBaseURL: defaultCdnBaseURL, + esm: false, } } +// NewESM returns a new Client with ESM mode enabled +func NewESM() *Client { + return &Client{ + apiBaseURL: defaultApiBaseURL, + cdnBaseURL: defaultCdnBaseURL, + esm: true, + } +} + +// SetESM sets whether the client should use ESM mode +func (c *Client) SetESM(useESM bool) *Client { + c.esm = useESM + return c +} + +// FetchPackageFiles retrieves package files from jsdelivr func (c *Client) FetchPackageFiles(ctx context.Context, name, version string) (library.Files, string, error) { url := defaultApiBaseURL + name @@ -98,7 +116,7 @@ func (c *Client) FetchPackageFiles(ctx context.Context, name, version string) (l } } - // get all the files + // get all the files regardless of ESM mode - we need them for CSS and other file types vUrl := fmt.Sprintf("%s%s@%s", defaultApiBaseURL, name, useVersion) req, err = http.NewRequestWithContext(ctx, http.MethodGet, vUrl, nil) @@ -131,6 +149,30 @@ func (c *Client) FetchPackageFiles(ctx context.Context, name, version string) (l var files = walkFiles(pr.Files, basePath, "", hasDist) + // If ESM mode is enabled, we'll replace JS files with the ESM version + if c.esm { + // Create special ESM file with a unique LocalPath that will match any pattern + esmBasePath := c.cdnBaseURL + name + "@" + useVersion + "/+esm" + + // Use a simpler approach - just add the ESM bundle with a standard path + esmFile := library.File{ + Type: library.FileTypeJS, + Path: esmBasePath, + LocalPath: "/esm-bundle.js", // Simple filename without special characters + } + + // Filter out JavaScript files, keeping only CSS and other files + var nonJSFiles library.Files + for _, file := range files { + if file.Type != library.FileTypeJS { + nonJSFiles = append(nonJSFiles, file) + } + } + + // Combine the ESM file with non-JS files + files = append(library.Files{esmFile}, nonJSFiles...) + } + return files, useVersion, nil }