summaryrefslogtreecommitdiff
path: root/node_modules/esm-import-transformer
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/esm-import-transformer')
-rw-r--r--node_modules/esm-import-transformer/README.md91
-rw-r--r--node_modules/esm-import-transformer/import-transformer.js232
-rw-r--r--node_modules/esm-import-transformer/package.json26
3 files changed, 349 insertions, 0 deletions
diff --git a/node_modules/esm-import-transformer/README.md b/node_modules/esm-import-transformer/README.md
new file mode 100644
index 0000000..3b9a8bb
--- /dev/null
+++ b/node_modules/esm-import-transformer/README.md
@@ -0,0 +1,91 @@
+# esm-import-transformer
+
+Can transform any ESM source code `import` URLs using an import maps object. This package works in ESM or CJS.
+
+```js
+// Input source code:
+import {html, css, LitElement} from "lit";
+
+// Transform with an import map:
+import {html, css, LitElement} from "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js";
+
+// Or transform to a dynamic import:
+const {html, css, LitElement} = await import("lit");
+
+// Or transform to CommonJS require:
+const {html, css, LitElement} = require("lit");
+```
+
+## Usage
+
+```js
+// ESM
+import { ImportTransformer } from "esm-import-transformer";
+
+// or CJS
+const { ImportTransformer } = await import("esm-import-transformer");
+```
+
+### Transform with an import map
+
+Pass in a source code string and an [import maps](https://github.com/WICG/import-maps) object.
+
+```js
+let sourceCode = `import {html, css, LitElement} from "lit";`;
+let it = new ImportTransformer(sourceCode);
+
+let importMap = {
+ imports: {
+ lit: "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js"
+ }
+};
+let outputCode = it.transformWithImportMap(importMap);
+// returns: `import {html, css, LitElement} from "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js";`
+```
+
+### Transform to dynamic `import()`
+
+```js
+let sourceCode = `import {html, css, LitElement} from "lit";`;
+let it = new ImportTransformer(sourceCode);
+
+let outputCode = it.transformToDynamicImport();
+// returns: `const {html, css, LitElement} = await import("lit");`
+```
+
+### Transform to `require()`
+
+_Added in v3.0.1_: This method does _not_ require that the downstream package is CommonJS, but remember that _running_ the resulting code will fail if you try to `require` an ESM package (in some JavaScript environments, e.g. Node < 20).
+
+```js
+let sourceCode = `import {html, css, LitElement} from "lit";`;
+let it = new ImportTransformer(sourceCode);
+
+let outputCode = it.transformToRequire();
+// returns: `const {html, css, LitElement} = require("lit");`
+```
+
+### Has imports?
+
+_Added in v3.0.2_ Returns true if the code has any top level `import`.
+
+```js
+let sourceCode = `import {html, css, LitElement} from "lit";`;
+let it = new ImportTransformer(sourceCode);
+it.hasImports(); // true
+```
+
+```js
+let sourceCode = `const {html, css, LitElement} = require("lit");`;
+let it = new ImportTransformer(sourceCode);
+it.hasImports(); // false
+```
+
+
+## Installation
+
+Available on [npm](https://www.npmjs.com/package/esm-import-transformer)
+
+```
+npm install esm-import-transformer
+```
diff --git a/node_modules/esm-import-transformer/import-transformer.js b/node_modules/esm-import-transformer/import-transformer.js
new file mode 100644
index 0000000..4b09aa1
--- /dev/null
+++ b/node_modules/esm-import-transformer/import-transformer.js
@@ -0,0 +1,232 @@
+import { parse } from "acorn";
+
+const COMMENT_START = "/* ";
+const COMMENT_END = " */";
+const EXPORT_STR = "export ";
+
+export class ImportTransformer {
+ constructor(input, ast) {
+ this.parse(input, ast);
+ }
+
+ parse(input, ast) {
+ if(!input) {
+ throw new Error("Missing input to ImportTransformer, received: " + input)
+ }
+
+ this.originalSource = input;
+
+ if(ast) {
+ this.ast = ast;
+ } else {
+ this.ast = parse(input, {
+ sourceType: "module",
+ ecmaVersion: "latest"
+ });
+ }
+
+ this.imports = new Set();
+ this.exports = new Set();
+ this.namedExports = new Set();
+ }
+
+ static commentNode(str, sourceNode, indexOffset = 0) {
+ let { start, end } = sourceNode;
+ let statement = str.slice(start + indexOffset, end + indexOffset);
+ return {
+ statement,
+ code: `${str.slice(0, start + indexOffset)}${COMMENT_START}${statement}${COMMENT_END}${str.slice(end + indexOffset)}`,
+ offset: COMMENT_START.length + COMMENT_END.length,
+ };
+ }
+
+ static commentExportDeclarationOnly(str, sourceNode, indexOffset = 0) {
+ let { start, end } = sourceNode;
+ let statement = str.slice(start + indexOffset, end + indexOffset);
+
+ let functionDeclarationName = sourceNode.declaration?.id?.name;
+ let variableIdentifierNames = (sourceNode.declaration?.declarations || []).map(node => {
+ if(node.id.properties) {
+ return node.id.properties.map(node => node.key.name)
+ } else if(node.id.name) {
+ return node.id.name;
+ }
+
+ throw new Error("Could not find variable identifier in declaration for: " + statement);
+ }).flat();
+
+ let reuseStatement;
+ // change `export const a = 1;` to `export { a };` for reuse
+ if(functionDeclarationName || variableIdentifierNames.length > 0) {
+ reuseStatement = `export { ${functionDeclarationName || variableIdentifierNames.join(", ") } };`;
+ } else {
+ throw new Error("Couldn’t find identifier name for: " + statement);
+ }
+
+ // -1 there removes the double space between `export ` and ` */`
+ let commented = `${COMMENT_START}${EXPORT_STR.slice(0, -1)}${COMMENT_END}${statement.slice(EXPORT_STR.length)}`
+ return {
+ statement: reuseStatement,
+ namedExports: functionDeclarationName ? [functionDeclarationName] : variableIdentifierNames,
+ code: `${str.slice(0, start + indexOffset)}${commented}${str.slice(end + indexOffset)}`,
+ offset: COMMENT_START.length + COMMENT_END.length - 1, // -1 removes the double space between `export ` and ` */`
+ };
+ }
+
+ static transformImportSource(str, sourceNode, indexOffset = 0, importMap = {}) {
+ let { start, end, value } = sourceNode;
+ // Could be improved by https://www.npmjs.com/package/@import-maps/resolve
+ let resolved = importMap?.imports && importMap?.imports[value];
+ if(resolved) {
+ return {
+ code: `${str.slice(0, start + 1 + indexOffset)}${resolved}${str.slice(end - 1 + indexOffset)}`,
+ offset: resolved.length - value.length,
+ };
+ }
+ return {
+ code: str,
+ offset: 0
+ };
+ }
+
+ static transformImportCode(prefix, str, node, specifiers, sourceNode, indexOffset = 0) {
+ let { start, end } = node;
+ let endOffset = end - sourceNode.end;
+
+ start += indexOffset;
+ end += indexOffset;
+
+ let { raw: rawSourceValue } = sourceNode;
+ let importDeclaration = str.slice(start, end);
+
+ let specifierIndexes = [];
+ if(importDeclaration.startsWith("import * as ")) {
+ specifierIndexes[0] = "import * as ".length + start;
+ } else if(importDeclaration.startsWith("import ")) {
+ specifierIndexes[0] = "import ".length + start;
+ } else {
+ throw new Error(`Could not find \`import\` in import declaration: ${importDeclaration}`);
+ }
+
+ specifierIndexes[1] = specifiers[specifiers.length - 1].end + indexOffset;
+
+ // normalize away trailing } on import { a, b, c } specifiers
+ let split = str.slice(specifierIndexes[1]).split(" from ");
+ if(split.length > 0) {
+ specifierIndexes[1] += split[0].length;
+ }
+
+ let newImportString = `const ${str.slice(specifierIndexes[0], specifierIndexes[1])} = ${prefix}(${rawSourceValue})`;
+ let returnedCode = str.slice(0, start) + newImportString + str.slice(end - endOffset);
+
+ return {
+ code: returnedCode,
+ offset: returnedCode.length - str.length,
+ };
+ }
+
+ _transform(prefix) {
+ let input = this.originalSource;
+ let indexOffset = 0;
+ for(let node of this.ast.body) {
+ if(node.type === "ImportDeclaration") {
+ let ret = ImportTransformer.transformImportCode(prefix, input, node, node.specifiers, node.source, indexOffset)
+ input = ret.code;
+ indexOffset += ret.offset;
+ }
+ }
+
+ return input;
+ }
+
+ transformToDynamicImport() {
+ return this._transform("await import");
+ }
+
+ transformToRequire() {
+ return this._transform("require");
+ }
+
+ // alias for backwards compat
+ transform(...args) {
+ return this.transformWithImportMap(...args);
+ }
+
+ transformRemoveImportExports() {
+ let input = this.originalSource;
+ let indexOffset = 0;
+ for(let node of this.ast.body) {
+ if(node.type === "ImportDeclaration") {
+ let ret = ImportTransformer.commentNode(input, node, indexOffset);
+ input = ret.code;
+ indexOffset += ret.offset;
+ this.imports.add(ret.statement);
+ } else if(node.type?.startsWith("Export")) {
+ let ret;
+ // comment out `export { name }` and `export default`
+ if(node.type === "ExportNamedDeclaration" && node.specifiers.length > 0 || node.type === "ExportDefaultDeclaration") {
+ ret = ImportTransformer.commentNode(input, node, indexOffset);
+ if(node.type === "ExportDefaultDeclaration") {
+ this.namedExports.add("default");
+ } else {
+ for(let specifierNode of node.specifiers || []) {
+ if(specifierNode?.exported?.name) {
+ this.namedExports.add(specifierNode.exported.name);
+ }
+ }
+ }
+ } else {
+ // just comment out start `export ` from the beginning of `export const` or `export function`
+ ret = ImportTransformer.commentExportDeclarationOnly(input, node, indexOffset);
+ for(let name of ret.namedExports) {
+ this.namedExports.add(name);
+ }
+ }
+
+ input = ret.code;
+ indexOffset += ret.offset;
+ this.exports.add(ret.statement);
+ }
+ }
+
+ return input;
+ }
+
+ getImportsAndExports() {
+ return {
+ imports: this.imports,
+ exports: this.exports,
+ namedExports: this.namedExports,
+ };
+ }
+
+ transformWithImportMap(importMap) {
+ if(!importMap) {
+ return this.originalSource;
+ }
+
+ let input = this.originalSource;
+ let indexOffset = 0;
+ for(let node of this.ast.body) {
+ if(node.type === "ImportDeclaration") {
+ if(importMap?.imports) {
+ let ret = ImportTransformer.transformImportSource(input, node.source, indexOffset, importMap);
+ input = ret.code;
+ indexOffset += ret.offset;
+ }
+ }
+ }
+
+ return input;
+ }
+
+ hasImports() {
+ for(let node of this.ast.body) {
+ if(node.type === "ImportDeclaration") {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/node_modules/esm-import-transformer/package.json b/node_modules/esm-import-transformer/package.json
new file mode 100644
index 0000000..fa9c624
--- /dev/null
+++ b/node_modules/esm-import-transformer/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "esm-import-transformer",
+ "version": "3.0.5",
+ "description": "Perform transformations on ESM import syntax (using import maps or to a dynamic import).",
+ "type": "module",
+ "main": "./import-transformer.js",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/zachleat/esm-import-transformer.git"
+ },
+ "author": {
+ "name": "Zach Leatherman",
+ "email": "zachleatherman@gmail.com",
+ "url": "https://zachleat.com/"
+ },
+ "license": "MIT",
+ "scripts": {
+ "test": "npx ava"
+ },
+ "dependencies": {
+ "acorn": "^8.15.0"
+ },
+ "devDependencies": {
+ "ava": "^6.4.1"
+ }
+}