Code Monkey home page Code Monkey logo

rewrite-imports's Introduction

rewrite-imports CI

A tiny (349B) utility to transform various import statements into require() calls, using regular expressions.

Looking for something more backwards compatible?
Check out v1.4.0 which does not rely on destructured assignment!

Caveats

This module returns a string and does not provide a runtime nor does it evaluate the output.

💡 For this behavior, use rewrite-module or check out @taskr/esnext for an example.

The output requires a JavaScript runtime that supports require calls and destructuring assignments with Objects.

  • At least Node 6.x is required

  • Or, for browsers:

    • A require shim is always needed – see fn
    • Ensure your target browsers support destructuring – see chart

If you have false positives, you may want to use an AST to find actual import statements before transformation.

Check out an example implementation.

Install

$ npm install --save rewrite-imports

Usage

import { rewrite } from 'rewrite-imports';
// or
const { rewrite } = require('rewrite-imports');

rewrite(`import foo from '../bar'`);
//=> const foo = require('../bar');

rewrite(`import { foo } from 'bar'`);
//=> const { foo } = require('bar');

rewrite(`import * as path from 'path';`);
//=> const path = require('path');

rewrite(`import { foo as bar, baz as bat, lol } from 'quz';`);
//=> const { foo:bar, baz:bat, lol } = require('quz');

rewrite(`import foobar, { foo as FOO, bar } from 'foobar';`);
//=> const foobar = require('foobar');
//=> const { foo:FOO, bar } = foobar;

API

rewrite(input, fn)

input

Type: String

The import statement(s) or the code containing import statement(s).

See MDN for valid import statement syntax.

fn

Type: String
Default: 'require'

The require-like function name to use. Defaults to require but you may choose to pass the name of a custom shim function; for example, __webpack_require__ may work for webpack in the browser.

License

MIT © Luke Edwards

rewrite-imports's People

Contributors

lukeed avatar sapegin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

rewrite-imports's Issues

Incorrect transformation

Greetings. I maintain esbuild-svelte and recently ran across what I believe is an incorrect transform. The version w/ the incorrect code is v0.5.5 (see line 23) and I did a "emergency" fix with v0.5.6 that solved the issue (by disabling the new code I added).

Minimum reproduction, removing the declaration of filename, contents or the text property containing doesn't causes the code to transform just fine. I've replaced any text that didn't seem to matter with N/A

import { relative } from "path";
function sveltePlugin() {
  return {
    name: "N/A",
    setup(build) {
      build.onLoad({ filter: /N\/A/ }, () => {
        return {
          errors: [
            {
              text: "doesn't"
            }
          ]
        };
      });
      build.onLoad({ filter: /N\/A/ }, (args) => {
        let filename = relative(process.cwd(), args.path);
        let contents = `N/A
import "${"something"}";`;
        return null;
      });
    }
  };
}
export {
  sveltePlugin as default
};

The unexpected result is:

require(";`);
        return null;
      });
    }
  };
}
export {
  sveltePlugin as default
};

I know this can get real complex for parsing! I see the false positives warning and #8 so please close this if it's out of scope to fix, just figured I'd pass on a semi-real world example.

Thanks for your work!

Transform to partials

@sapegin What do you think about transforming imports to their more succinct require counterparts?

import { foo, bar } from 'foobar';
//=> const { foo, bar } = require('foobar');

In order to do this safely, we just have to check that
a) there is no alias (as) attempt
b) there is no mixed import statement (#10)

If either of those are true, we have to bail and fallback to the current transformation.

Similarly, it might be nice to do the aliasing/partials with destructuring. I think that transforming those is the role of a Babel-type player.

Given your use-case, I'm interested in your thoughts. This probably warrants a 2.0 given the change in output.

import foobar, { foo, bar } from 'foobar';

// Current:
const foobar = require('foobar');
const foo = foobar.foo;
const bar = foobar.bar;

// After:
const foobar = require('foobar');
const { foo, bar } = foobar;


import { foo as FOO, bar } from 'foobar';

// Current:
const foobar = require('foobar');
const FOO = foobar.foo;
const bar = foobar.bar;

// After:
const foobar = require('foobar');
const { foo:FOO, bar } = foobar;
//^ Still Node 6.x compatible

default support

Based on your examples provided, I don't think you are properly supporting esm imports.

const rImports = require('rewrite-imports');

rImports(`import * as a from './a';`);
//=> const a = require('./a');

rImports(`import a from './a';`);
//=> const a = require('./a').default;

rImports(`import { default as a } from './a';`);
//=> const { default: a } = require('./a');

rImports(`import a, { default as b } from './a';`);
//=> const a = require('./a').default;
//=> const { default: b } = require('./a');

This is because import a from './a' !== import * as a from './a'

False positives

I found a few false positive cases, where the library replaces imports where it shouldn't. But I'm not sure trying to fix that will be in the scope of the library. Probably I'll just allow imports only at the beginning of the file — they supposed to be hoisted anyway.

const line = "import foo from 'foo'"
const line = 'import foo from "foo"'
const line = `import foo from 'foo'`
<p>import foo from 'foo'</p>

Mixed imports don't work

For this input:

rewriteImports(`import bar, { foo } from 'bar'`);

The result would be:

function ri$interop(m){return m.default||m}
const bar = ri$interop(require('bar'));
const foo = bar.foo;'

bar will be already m.default, so foo will be m.default.foo which is incorrect.

And I'm not really sure we should try to solve it in the library itself, probably just removing interop would be a better solution. I'm still using 1.2 in Styleguidist because of that — I need a custom interop function.

Maybe we could make require function name configurable, so users could have their custom implementation before calling actual require.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.