importmap-rails icon indicating copy to clipboard operation
importmap-rails copied to clipboard

Introduce `preserve_extname` option for directory pin

Open songjiz opened this issue 5 months ago • 0 comments

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.

songjiz avatar Sep 12 '24 07:09 songjiz