// FIXME: es-module-shim won’t shim the dynamic import without this explicit import import “@hotwired/stimulus”
const controllerAttribute = “data-controller”
// Eager load all controllers registered beneath the ‘under` path in the import map to the passed application instance. export function eagerLoadControllersFrom(under, application) {
const paths = Object.keys(parseImportmapJson()).filter(path => path.match(new RegExp(`^${under}/.*_controller$`))) paths.forEach(path => registerControllerFromPath(path, under, application))
}
function parseImportmapJson() {
return JSON.parse(document.querySelector("script[type=importmap]").text).imports
}
function registerControllerFromPath(path, under, application) {
const name = path .replace(new RegExp(`^${under}/`), "") .replace("_controller", "") .replace(/\//g, "--") .replace(/_/g, "-") if (canRegisterController(name, application)) { import(path) .then(module => registerController(name, module, application)) .catch(error => console.error(`Failed to register controller: ${name} (${path})`, error)) }
}
// Lazy load controllers registered beneath the ‘under` path in the import map to the passed application instance. export function lazyLoadControllersFrom(under, application, element = document) {
lazyLoadExistingControllers(under, application, element) lazyLoadNewControllers(under, application, element)
}
function lazyLoadExistingControllers(under, application, element) {
queryControllerNamesWithin(element).forEach(controllerName => loadController(controllerName, under, application))
}
function lazyLoadNewControllers(under, application, element) {
new MutationObserver((mutationsList) => { for (const { attributeName, target, type } of mutationsList) { switch (type) { case "attributes": { if (attributeName == controllerAttribute && target.getAttribute(controllerAttribute)) { extractControllerNamesFrom(target).forEach(controllerName => loadController(controllerName, under, application)) } } case "childList": { lazyLoadExistingControllers(under, application, target) } } } }).observe(element, { attributeFilter: [controllerAttribute], subtree: true, childList: true })
}
function queryControllerNamesWithin(element) {
return Array.from(element.querySelectorAll(`[${controllerAttribute}]`)).map(extractControllerNamesFrom).flat()
}
function extractControllerNamesFrom(element) {
return element.getAttribute(controllerAttribute).split(/\s+/).filter(content => content.length)
}
function loadController(name, under, application) {
if (canRegisterController(name, application)) { import(controllerFilename(name, under)) .then(module => registerController(name, module, application)) .catch(error => console.error(`Failed to autoload controller: ${name}`, error)) }
}
function controllerFilename(name, under) {
return `${under}/${name.replace(/--/g, "/").replace(/-/g, "_")}_controller`
}
function registerController(name, module, application) {
if (canRegisterController(name, application)) { application.register(name, module.default) }
}
function canRegisterController(name, application){
return !application.router.modulesByIdentifier.has(name)
}