importmap-rails
importmap-rails copied to clipboard
Introduce `preserve_extname` option for directory pin
This PR enhances the pin_all_from
method to properly handle file extensions when pinning directories. It introduces a preserve_extname
option to retain file extensions when needed, addressing compatibility issues with libraries like Shoelace that require .js extensions in their import statements.
Background
Shoelace's autoloader uses import statements that include the .js extension:
...
function register(tagName) {
if (customElements.get(tagName)) {
return Promise.resolve();
}
const tagWithoutPrefix = tagName.replace(/^sl-/i, "");
const path = getBasePath(`components/${tagWithoutPrefix}/${tagWithoutPrefix}.js`);
return new Promise((resolve, reject) => {
import(path).then(() => resolve()).catch(() => reject(new Error(`Unable to autoload <${tagName}> from ${path}`)));
});
}
The current importmap implementation removes file extensions by default, which can break Shoelace's autoloader functionality.
Usage Example
pin "application"
pin "@hotwired/turbo-rails", to: "turbo.min.js"
pin "@hotwired/stimulus", to: "stimulus.min.js"
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
pin_all_from "app/javascript/controllers", under: "controllers"
pin_all_from "vendor/javascript/@shoelace-style/shoelace/cdn", under: "@shoelace-style/shoelace/cdn", preserve_extname: true, preload: false
// app/javascript/application.js
import "@hotwired/turbo-rails"
import "controllers"
import "@shoelace-style/shoelace/cdn/shoelace-autoloader.js"
With these changes, Shoelace can now correctly import components under "@shoelace-style/shoelace/cdn/" while maintaining compatibility with other libraries that don't require extensions.