1// FIXME: es-module-shim won't shim the dynamic import without this explicit import 2import "@hotwired/stimulus" 3 4const controllerAttribute = "data-controller" 5 6// Eager load all controllers registered beneath the `under` path in the import map to the passed application instance. 7export function eagerLoadControllersFrom(under, application) { 8 const paths = Object.keys(parseImportmapJson()).filter(path => path.match(new RegExp(`^${under}/.*_controller$`))) 9 paths.forEach(path => registerControllerFromPath(path, under, application)) 10} 11 12function parseImportmapJson() { 13 return JSON.parse(document.querySelector("script[type=importmap]").text).imports 14} 15 16function registerControllerFromPath(path, under, application) { 17 const name = path 18 .replace(new RegExp(`^${under}/`), "") 19 .replace("_controller", "") 20 .replace(/\//g, "--") 21 .replace(/_/g, "-") 22 23 if (canRegisterController(name, application)) { 24 import(path) 25 .then(module => registerController(name, module, application)) 26 .catch(error => console.error(`Failed to register controller: ${name} (${path})`, error)) 27 } 28} 29 30 31// Lazy load controllers registered beneath the `under` path in the import map to the passed application instance. 32export function lazyLoadControllersFrom(under, application, element = document) { 33 lazyLoadExistingControllers(under, application, element) 34 lazyLoadNewControllers(under, application, element) 35} 36 37function lazyLoadExistingControllers(under, application, element) { 38 queryControllerNamesWithin(element).forEach(controllerName => loadController(controllerName, under, application)) 39} 40 41function lazyLoadNewControllers(under, application, element) { 42 new MutationObserver((mutationsList) => { 43 for (const { attributeName, target, type } of mutationsList) { 44 switch (type) { 45 case "attributes": { 46 if (attributeName == controllerAttribute && target.getAttribute(controllerAttribute)) { 47 extractControllerNamesFrom(target).forEach(controllerName => loadController(controllerName, under, application)) 48 } 49 } 50 51 case "childList": { 52 lazyLoadExistingControllers(under, application, target) 53 } 54 } 55 } 56 }).observe(element, { attributeFilter: [controllerAttribute], subtree: true, childList: true }) 57} 58 59function queryControllerNamesWithin(element) { 60 return Array.from(element.querySelectorAll(`[${controllerAttribute}]`)).map(extractControllerNamesFrom).flat() 61} 62 63function extractControllerNamesFrom(element) { 64 return element.getAttribute(controllerAttribute).split(/\s+/).filter(content => content.length) 65} 66 67function loadController(name, under, application) { 68 if (canRegisterController(name, application)) { 69 import(controllerFilename(name, under)) 70 .then(module => registerController(name, module, application)) 71 .catch(error => console.error(`Failed to autoload controller: ${name}`, error)) 72 } 73} 74 75function controllerFilename(name, under) { 76 return `${under}/${name.replace(/--/g, "/").replace(/-/g, "_")}_controller` 77} 78 79function registerController(name, module, application) { 80 if (canRegisterController(name, application)) { 81 application.register(name, module.default) 82 } 83} 84 85function canRegisterController(name, application){ 86 return !application.router.modulesByIdentifier.has(name) 87}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.