kopia lustrzana https://github.com/shoelace-style/shoelace
add autoloader prototype
rodzic
a4131caeda
commit
a32488baeb
|
@ -9,6 +9,9 @@
|
||||||
"atrule",
|
"atrule",
|
||||||
"autocorrect",
|
"autocorrect",
|
||||||
"autofix",
|
"autofix",
|
||||||
|
"autoload",
|
||||||
|
"autoloader",
|
||||||
|
"autoloading",
|
||||||
"autoplay",
|
"autoplay",
|
||||||
"bezier",
|
"bezier",
|
||||||
"boxicons",
|
"boxicons",
|
||||||
|
|
|
@ -8,6 +8,8 @@ New versions of Shoelace are released as-needed and generally occur when a criti
|
||||||
|
|
||||||
## Next
|
## Next
|
||||||
|
|
||||||
|
- Added an experimental autoloader
|
||||||
|
- Added the `subpath` argument to `getBasePath()` to make it easier to generate full paths to any file
|
||||||
- Fixed a bug in `<sl-select>` that caused the display label to render incorrectly in Chrome after form validation [#1197](https://github.com/shoelace-style/shoelace/discussions/1197)
|
- Fixed a bug in `<sl-select>` that caused the display label to render incorrectly in Chrome after form validation [#1197](https://github.com/shoelace-style/shoelace/discussions/1197)
|
||||||
- Fixed a bug in `<sl-input>` that prevented users from applying their own value for `autocapitalize`, `autocomplete`, and `autocorrect` when using `type="password` [#1205](https://github.com/shoelace-style/shoelace/issues/1205)
|
- Fixed a bug in `<sl-input>` that prevented users from applying their own value for `autocapitalize`, `autocomplete`, and `autocorrect` when using `type="password` [#1205](https://github.com/shoelace-style/shoelace/issues/1205)
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,8 @@ fs.mkdirSync(outdir, { recursive: true });
|
||||||
//
|
//
|
||||||
// The whole shebang
|
// The whole shebang
|
||||||
'./src/shoelace.ts',
|
'./src/shoelace.ts',
|
||||||
|
// The auto-loader
|
||||||
|
'./src/shoelace-autoloader.ts',
|
||||||
// Components
|
// Components
|
||||||
...(await globby('./src/components/**/!(*.(style|test)).ts')),
|
...(await globby('./src/components/**/!(*.(style|test)).ts')),
|
||||||
// Translations
|
// Translations
|
||||||
|
@ -120,6 +122,22 @@ fs.mkdirSync(outdir, { recursive: true });
|
||||||
routes: {
|
routes: {
|
||||||
'/dist': './dist'
|
'/dist': './dist'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
//
|
||||||
|
// Suppress Chrome's document.write() warning
|
||||||
|
//
|
||||||
|
// More info: https://github.com/BrowserSync/browser-sync/issues/1600)
|
||||||
|
//
|
||||||
|
snippetOptions: {
|
||||||
|
rule: {
|
||||||
|
match: /<\/head>/u,
|
||||||
|
fn: (snippet, match) => {
|
||||||
|
const {
|
||||||
|
groups: { src }
|
||||||
|
} = /src='(?<src>[^']+)'/u.exec(snippet);
|
||||||
|
return `<script src="${src}" async></script>${match}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import type { IconLibrary } from './library';
|
||||||
|
|
||||||
const library: IconLibrary = {
|
const library: IconLibrary = {
|
||||||
name: 'default',
|
name: 'default',
|
||||||
resolver: name => `${getBasePath()}/assets/icons/${name}.svg`
|
resolver: name => getBasePath(`assets/icons/${name}.svg`)
|
||||||
};
|
};
|
||||||
|
|
||||||
export default library;
|
export default library;
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
import { getBasePath } from './utilities/base-path';
|
||||||
|
|
||||||
|
const observer = new MutationObserver(mutations => {
|
||||||
|
for (const { addedNodes } of mutations) {
|
||||||
|
for (const node of addedNodes) {
|
||||||
|
if (node.nodeType === Node.ELEMENT_NODE) {
|
||||||
|
discover(node as Element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks a node for undefined elements and attempts to register them.
|
||||||
|
*/
|
||||||
|
async function discover(root: Element) {
|
||||||
|
const rootTagName = root.tagName.toLowerCase();
|
||||||
|
const rootIsCustomElement = rootTagName.includes('-');
|
||||||
|
const tags = [...root.querySelectorAll(':not(:defined)')]
|
||||||
|
.map(el => el.tagName.toLowerCase())
|
||||||
|
.filter(tag => tag.startsWith('sl-'));
|
||||||
|
|
||||||
|
// If the root element is an undefined custom element, add it to the list
|
||||||
|
if (rootIsCustomElement && !customElements.get(rootTagName)) {
|
||||||
|
tags.push(root.tagName.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the list unique
|
||||||
|
const tagsToRegister = [...new Set(tags)];
|
||||||
|
|
||||||
|
await Promise.allSettled(tagsToRegister.map(tagName => register(tagName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers an element by tag name.
|
||||||
|
*/
|
||||||
|
function register(tagName: string): Promise<void> {
|
||||||
|
const tagWithoutPrefix = tagName.replace(/^sl-/i, '');
|
||||||
|
const path = getBasePath(`components/${tagWithoutPrefix}/${tagWithoutPrefix}.js`);
|
||||||
|
|
||||||
|
// If the element is already defined, there's nothing more to do
|
||||||
|
if (customElements.get(tagName)) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register it
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
import(path)
|
||||||
|
.then(() => resolve())
|
||||||
|
.catch(() => reject(new Error(`Unable to automatically load<${tagName}> from ${path}`)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial discovery
|
||||||
|
discover(document.body);
|
||||||
|
|
||||||
|
// Listen for new undefined elements
|
||||||
|
observer.observe(document.body, { subtree: true, childList: true });
|
|
@ -3,6 +3,7 @@
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
||||||
"target": "es2017",
|
"target": "es2017",
|
||||||
|
"module": "es2020",
|
||||||
"lib": [
|
"lib": [
|
||||||
"dom",
|
"dom",
|
||||||
"dom.Iterable",
|
"dom.Iterable",
|
||||||
|
|
Ładowanie…
Reference in New Issue