diff --git a/README.md b/README.md
index f0a3403..24f5bc3 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,20 @@ The import-map-injector.js file must execute before any ES module is loaded by t
### Via `` elements.
+
+```html
+
+
+
+
+
+
+
+
+
+
+```
### Via npm
@@ -39,7 +52,7 @@ It's better for performance to put the import statement at the top of your bundl
## Usage
-import-map-injector combines multiple `` elements into a final `` element, which is injected into the `
` element of the web page. The browser spec for import maps requires the `` to be injected before any ES modules are loaded via `` elements into a final `` element, which is injected into the `` element of the web page. The browser spec for import maps requires the `` to be injected before any ES modules are loaded via `
+
+
+
+
+
+```
+
+#### Asynchronous import map installation
+
+When using external import maps, import-map-injector must wait for the network request(s) loading external import map(s) to complete before it can install the browser-native import map. This means you cannot use `
+
+
+
```
-
-### `
+
+
+
+
+
+
+
+
+
+
diff --git a/src/import-map-injector.ts b/src/import-map-injector.ts
index 4e38c7e..5e12027 100644
--- a/src/import-map-injector.ts
+++ b/src/import-map-injector.ts
@@ -5,84 +5,110 @@ interface ImportMap {
type SpecifierMap = Record;
-const jsonPromises: Promise[] = [];
+const importMapJsons: (Promise | ImportMap)[] = [];
const errPrefix = "import-map-injector:";
-document
- .querySelectorAll("script[type=injector-importmap]")
- .forEach((scriptEl) => {
- if (scriptEl.src) {
- jsonPromises.push(
- fetch(scriptEl.src)
- .then((r: Response) => {
- if (r.ok) {
- if (
- r.headers.get("content-type").toLowerCase() !==
- "application/importmap+json"
- ) {
- throw Error(
- `${errPrefix} Import map at url '${scriptEl.src}' does not have the required content-type http response header. Must be 'application/importmap+json'`,
- );
- }
+const injectorImportMaps = document.querySelectorAll(
+ "script[type=injector-importmap]",
+);
- return r.json();
- } else {
+injectorImportMaps.forEach((scriptEl) => {
+ if (scriptEl.src) {
+ importMapJsons.push(
+ fetch(scriptEl.src)
+ .then((r: Response) => {
+ if (r.ok) {
+ if (
+ r.headers.get("content-type").toLowerCase() !==
+ "application/importmap+json"
+ ) {
throw Error(
- `${errPrefix} import map at url '${scriptEl.src}' must respond with a success HTTP status, but responded with HTTP ${r.status} ${r.statusText}`,
+ `${errPrefix} Import map at url '${scriptEl.src}' does not have the required content-type http response header. Must be 'application/importmap+json'`,
);
}
- })
- .catch((err) => {
- console.error(
- `${errPrefix} Error loading import map from URL '${scriptEl.src}'`,
+
+ return r.json();
+ } else {
+ throw Error(
+ `${errPrefix} import map at url '${scriptEl.src}' must respond with a success HTTP status, but responded with HTTP ${r.status} ${r.statusText}`,
);
- throw err;
- }),
- );
- } else if (scriptEl.textContent.length > 0) {
- jsonPromises.push(
- Promise.resolve().then(() => JSON.parse(scriptEl.textContent)),
- );
- } else {
+ }
+ })
+ .catch((err) => {
+ console.error(
+ `${errPrefix} Error loading import map from URL '${scriptEl.src}'`,
+ );
+ throw err;
+ }),
+ );
+ } else if (scriptEl.textContent.length > 0) {
+ let json;
+ try {
+ json = JSON.parse(scriptEl.textContent);
+ } catch (err) {
+ console.error(err);
throw Error(
- `${errPrefix} Script with type "injector-importmap" does not contain an importmap`,
+ `${errPrefix} A