-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'FriedRiceNoodles:master' into master
- Loading branch information
Showing
16 changed files
with
320 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
// Inpired by https://github.com/shoelace-style/shoelace/blob/next/src/shoelace-autoloader.ts | ||
|
||
function getBasePath(subpath = '') { | ||
const scripts = [...document.getElementsByTagName('script')] as HTMLScriptElement[]; | ||
const autoloader = scripts.find((script) => script.src.includes('banana-autoloader')) as HTMLScriptElement; | ||
const basePath = autoloader.src.split('/').slice(0, -1).join('/'); | ||
|
||
// Return the base path without a trailing slash. If one exists, append the subpath separated by a slash. | ||
return basePath.replace(/\/$/, '') + (subpath ? `/${subpath.replace(/^\//, '')}` : ``); | ||
} | ||
|
||
const observer = new MutationObserver((mutations) => { | ||
for (const { addedNodes } of mutations) { | ||
for (const node of addedNodes) { | ||
if (node.nodeType === Node.ELEMENT_NODE) { | ||
void discover(node as Element); | ||
} | ||
} | ||
} | ||
}); | ||
|
||
/** | ||
* Checks a node for undefined elements and attempts to register them. | ||
*/ | ||
async function discover(root: Element | ShadowRoot) { | ||
if (!root) return; | ||
|
||
const rootTagName = root instanceof Element ? root.tagName.toLowerCase() : ''; | ||
const rootIsBananaElement = rootTagName?.toLowerCase().startsWith('b-'); | ||
const rootIsCustomElement = rootTagName?.includes('-'); | ||
|
||
const tags = [...root.querySelectorAll(':not(:defined)')] | ||
.map((el) => el.tagName.toLowerCase()) | ||
.filter((tag) => tag.startsWith('b-')); | ||
|
||
// If the root element is an undefined Banana component, add it to the list | ||
if (rootIsBananaElement && !customElements.get(rootTagName)) { | ||
tags.push(rootTagName); | ||
} | ||
|
||
// Make the list unique | ||
const tagsToRegister = [...new Set(tags)]; | ||
|
||
const notBananaCustomElements = [...root.querySelectorAll('*')].filter( | ||
(el) => el.tagName.includes('-') && !el.tagName.toLowerCase().startsWith('b-'), | ||
); | ||
|
||
// If the root element is a custom element and not a Banana component, add it to the list | ||
if (rootIsCustomElement && !rootIsBananaElement && root instanceof Element) { | ||
notBananaCustomElements.push(root); | ||
} | ||
|
||
// Discover any shadow roots | ||
const customElementsPromises = notBananaCustomElements.map((el) => { | ||
return customElements.whenDefined(el.tagName); | ||
}); | ||
void Promise.allSettled(customElementsPromises).then(() => { | ||
notBananaCustomElements.forEach((el) => { | ||
if (el.shadowRoot) void discover(el.shadowRoot); | ||
}); | ||
}); | ||
|
||
await Promise.allSettled(tagsToRegister.map((tagName) => register(tagName))); | ||
} | ||
|
||
/** | ||
* Registers an element by tag name. | ||
*/ | ||
function register(tagName: string): Promise<void> { | ||
// If the element is already defined, there's nothing more to do | ||
if (customElements.get(tagName)) { | ||
return Promise.resolve(); | ||
} | ||
|
||
const tagWithoutPrefix = tagName.replace(/^b-/i, ''); | ||
const path = getBasePath(`${tagWithoutPrefix}/index.js`); | ||
|
||
// Register it | ||
return new Promise((resolve, reject) => { | ||
import(path).then(() => resolve()).catch(() => reject(new Error(`Unable to autoload <${tagName}> from ${path}`))); | ||
}); | ||
} | ||
|
||
// Initial discovery | ||
void discover(document.body); | ||
|
||
// Listen for new undefined elements | ||
observer.observe(document.documentElement, { subtree: true, childList: true }); | ||
|
||
// BMessage is a special case because it's often used by window.BMessage methods but not directly in the DOM | ||
// If it's not defined, import it directly | ||
if (!customElements.get('b-message')) { | ||
// import the module | ||
const path = getBasePath('message/index.js'); | ||
void import(path); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.