diff --git a/package.json b/package.json
index 5602427a..360ad27f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@jsenv/importmap-node-module",
- "version": "7.1.1",
+ "version": "7.2.0",
"description": "Generate importmap for node_modules",
"license": "MIT",
"repository": {
diff --git a/src/cli.mjs b/src/cli.mjs
index cc58b04a..5f2189be 100755
--- a/src/cli.mjs
+++ b/src/cli.mjs
@@ -39,9 +39,10 @@ if (positionals.length > 1) {
if (
!outfile.endsWith(".html") &&
!outfile.endsWith(".importmap") &&
- !outfile.endsWith(".json")
+ !outfile.endsWith(".json") &&
+ !outfile.endsWith(".js")
) {
- console.error("Error: outfile must end with .html, .importmap or .json");
+ console.error("Error: outfile must end with .html, .importmap, .json or .js");
process.exit(1);
}
diff --git a/src/step_write_into_files/write_into_files.js b/src/step_write_into_files/write_into_files.js
index be08facf..de9b8c29 100644
--- a/src/step_write_into_files/write_into_files.js
+++ b/src/step_write_into_files/write_into_files.js
@@ -22,13 +22,19 @@ export const writeIntoFiles = (
const importmapAsJson = JSON.stringify(importmap, null, " ");
if (fileUrl.endsWith(".html")) {
writeIntoHtmlFile(fileUrl, importmapAsJson, { logger });
+ } else if (fileUrl.endsWith(".js")) {
+ writeInfoJsFile(fileUrl, importmapAsJson, { logger });
} else {
- writeFileSync(fileUrl, importmapAsJson);
- logger.info(`-> ${urlToFileSystemPath(fileUrl)}`);
+ writeIntoJsonFile(fileUrl, importmapAsJson, { logger });
}
}
};
+const writeIntoJsonFile = (jsonFileUrl, importmapAsJson, { logger }) => {
+ writeFileSync(jsonFileUrl, importmapAsJson);
+ logger.info(`-> ${urlToFileSystemPath(jsonFileUrl)}`);
+};
+
const writeIntoHtmlFile = (htmlFileUrl, importmapAsJson, { logger }) => {
const htmlAst = parseHtml({
html: readFileSync(htmlFileUrl, { as: "string" }),
@@ -80,3 +86,38 @@ const writeIntoHtmlFile = (htmlFileUrl, importmapAsJson, { logger }) => {
const html = stringifyHtmlAst(htmlAst);
writeFileSync(new URL(htmlFileUrl), html);
};
+
+const writeInfoJsFile = (jsFileUrl, importmapAsJson, { logger }) => {
+ const jsFileContent = `
+const currentScript = document.currentScript;
+if (!currentScript) {
+ throw new Error(
+ "document.currentScript is not available, cannot inject importmap"
+ );
+}
+const baseUrl = new URL(".", currentScript.src).href;
+const importmap = ${importmapAsJson};
+const topLevelMappings = importmap.imports;
+const scopedMappings = importmap.scopes;
+const makeMappingsAbsolute = () => {
+ for (const key of Object.keys(mappings)) {
+ mappings[key] = baseUrl + mappings[key];
+ }
+}
+if (topLevelMappings) {
+ makeMappingsAbsolute(topLevelMappings);
+}
+if (scopedMappings) {
+ for (const scope of Object.keys(scopedMappings)) {
+ const mappings = scopedMappings[scope];
+ makeMappingsAbsolute(mappings);
+ }
+}
+const importmapScript = document.createElement("script");
+importmapScript.type = "importmap";
+importmapScript.textContent = importmap;
+currentScript.after(importmapScript);
+`;
+ writeFileSync(jsFileUrl, jsFileContent);
+ logger.info(`-> ${urlToFileSystemPath(jsFileUrl)}`);
+};
diff --git a/tests/write_inside_js/_write_inside_js.test.mjs/0_basic/0_basic.md b/tests/write_inside_js/_write_inside_js.test.mjs/0_basic/0_basic.md
new file mode 100644
index 00000000..45b33501
--- /dev/null
+++ b/tests/write_inside_js/_write_inside_js.test.mjs/0_basic/0_basic.md
@@ -0,0 +1,92 @@
+# [0_basic](../../write_inside_js.test.mjs#L21)
+
+```js
+run("0_basic")
+```
+
+# 1/2 write 6 files into "./git_ignored/"
+
+## node_modules/foo/foo.js
+```js
+console.log('foo');
+```
+
+## node_modules/foo/package.json
+```json
+{
+ "name": "foo",
+ "main": "./foo.js",
+ "private": true
+}
+```
+
+## index.html
+```html
+
+
+
+ Title
+
+
+
+
+
+
+
+
+```
+
+## main.js
+```js
+import "foo";
+
+```
+
+## package.json
+```json
+{
+ "name": "root",
+ "private": true,
+ "dependencies": {
+ "foo": "*"
+ }
+}
+```
+
+## index.js
+
+```
+
+const currentScript = document.currentScript;
+if (!currentScript) {
+ throw new Error(
+ "document.currentScript is not available, cannot inject importmap"
+ );
+}
+const baseUrl = new URL(".", currentScript.src).href;
+const importmap = {
+ "imports": {
+ "root/": "./",
+ "foo/": "./node_modules/foo/",
+ "root": "./index",
+ "foo": "./node_modules/foo/foo.js"
+ },
+ "scopes": {}
+};
+const topLevelMappings = importmap.imports;
+const scopedMappings = importmap.scopes;
+const makeMappingsAbsolute = () => {
+```
+see [git_ignored/index.js](git_ignored/index.js) for more
+
+# 2/2 resolve
+
+```js
+undefined
+```
+
+---
+
+
+ Generated by @jsenv/snapshot
+
diff --git a/tests/write_inside_js/_write_inside_js.test.mjs/write_inside_js.test.mjs.md b/tests/write_inside_js/_write_inside_js.test.mjs/write_inside_js.test.mjs.md
new file mode 100644
index 00000000..3389c98b
--- /dev/null
+++ b/tests/write_inside_js/_write_inside_js.test.mjs/write_inside_js.test.mjs.md
@@ -0,0 +1,10 @@
+# [write_inside_js.test.mjs](../write_inside_js.test.mjs)
+
+
+- [0_basic](0_basic/0_basic.md)
+
+---
+
+
+ Generated by @jsenv/snapshot
+
diff --git a/tests/write_inside_js/fixtures/0_basic/index.html b/tests/write_inside_js/fixtures/0_basic/index.html
new file mode 100644
index 00000000..964be259
--- /dev/null
+++ b/tests/write_inside_js/fixtures/0_basic/index.html
@@ -0,0 +1,12 @@
+
+
+
+ Title
+
+
+
+
+
+
+
+
diff --git a/tests/write_inside_js/fixtures/0_basic/main.js b/tests/write_inside_js/fixtures/0_basic/main.js
new file mode 100644
index 00000000..c0748305
--- /dev/null
+++ b/tests/write_inside_js/fixtures/0_basic/main.js
@@ -0,0 +1 @@
+import "foo";
diff --git a/tests/write_inside_js/fixtures/0_basic/node_modules/foo/foo.js b/tests/write_inside_js/fixtures/0_basic/node_modules/foo/foo.js
new file mode 100644
index 00000000..3c800d3a
--- /dev/null
+++ b/tests/write_inside_js/fixtures/0_basic/node_modules/foo/foo.js
@@ -0,0 +1 @@
+console.log('foo');
\ No newline at end of file
diff --git a/tests/write_inside_js/fixtures/0_basic/node_modules/foo/package.json b/tests/write_inside_js/fixtures/0_basic/node_modules/foo/package.json
new file mode 100644
index 00000000..d48f02b9
--- /dev/null
+++ b/tests/write_inside_js/fixtures/0_basic/node_modules/foo/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "foo",
+ "main": "./foo.js",
+ "private": true
+}
\ No newline at end of file
diff --git a/tests/write_inside_js/fixtures/0_basic/package.json b/tests/write_inside_js/fixtures/0_basic/package.json
new file mode 100644
index 00000000..3453665e
--- /dev/null
+++ b/tests/write_inside_js/fixtures/0_basic/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "root",
+ "private": true,
+ "dependencies": {
+ "foo": "*"
+ }
+}
diff --git a/tests/write_inside_js/write_inside_js.test.mjs b/tests/write_inside_js/write_inside_js.test.mjs
new file mode 100644
index 00000000..479b7899
--- /dev/null
+++ b/tests/write_inside_js/write_inside_js.test.mjs
@@ -0,0 +1,22 @@
+import { replaceFileStructureSync } from "@jsenv/filesystem";
+import { writeImportmaps } from "@jsenv/importmap-node-module";
+import { snapshotWriteImportmaps } from "@jsenv/importmap-node-module/tests/snapshot_write_importmaps.js";
+
+const run = async (scenario, options) => {
+ replaceFileStructureSync({
+ from: new URL(`./fixtures/${scenario}/`, import.meta.url),
+ to: new URL("./git_ignored/", import.meta.url),
+ });
+ await writeImportmaps({
+ logLevel: "warn",
+ directoryUrl: new URL("./git_ignored/", import.meta.url),
+ importmaps: {
+ "index.js": {},
+ },
+ ...options,
+ });
+};
+
+await snapshotWriteImportmaps(import.meta.url, ({ test }) => {
+ test("0_basic", () => run("0_basic"));
+});