galooshi / import-js Goto Github PK
View Code? Open in Web Editor NEWA tool to simplify importing JS modules
License: MIT License
A tool to simplify importing JS modules
License: MIT License
Your code should typically not depend on devDependencies. It would be nice if import-js didn't match on files that were in node_modules directories that belong to devDependencies.
Now that import-js has extracted the core into a standalone gem, it can be integrated more easily with additional editors. We already have emacs and Sublime Text support and we should add Atom support.
If you have code and configuration that will result in fixing imports generating this:
import Blah, {
Bar,
Baz,
Bazz,
Buzz,
Fizz,
Foo,
Ooze,
Poo,
} from 'something';
running fix imports again incorrectly changes it to:
import Blah, {
Bar,
Baz,
Bazz,
Buzz,
Fizz,
Foo,
Ooze,
Poo,
} from
'something';
I have the following alias:
"aliases": {
"React": "react/addons"
},
And when I import React
, I get the following code:
const React = require('reactaddons');
but I expect to get:
const React = require('react/addons');
Sometimes when I run import-js, it takes a while for it to figure out what to import. I would like to set it up to run whenever I save a .js file so I can stop managing my require statements entirely, but before I do that it would be great if we could make this run faster.
One thing that might help would be to use some caching in the find_files
method. It might work well to swap out the Dir
calls for command line tools if they are available. Taking it a step further, it might be interesting to be able to optionally tap into other plugins' file listings, such as Command-T's file listing.
It would be nice if packages could add some data that would prevent consumers of the package from having to add a set of destructured properties to their import-js config. For instance, the set of things that could be destructured from underscore are pretty stable and don't really need to be defined for each individual consumer. Maybe this could be added to the package.json file or to a different file that is distributed with the package.
I am working in an application components are not structured into directories that contain index.jsx
, index.scss
, etc. In this structure, components are in files like MyComponent.jsx
and their styles are in files like MyComponent.scss
. In this case, it would be nice to be able to make a dynamic alias for styles
that resolves to the current filename plus .scss
.
If you have code and configuration that will result in fixing imports generating this:
import Blah, {
Bar,
Baz,
Bazz,
Buzz,
Fizz,
Foo,
Ooze,
Poo,
} from 'something';
and then removing some or all of the references to variables that are imported and run fix imports again, all of them stay. This does not seem to be a problem with imports that are not destructured.
Similar to #26:
index.js
may resolve to another file if defined in thepackage.json
So if you have a node_module
at something like node_modules/my-package/dist/my-package.js
and the package.json
file in that directory defines its main
as dist/my-package.js
, it would be really great if import-js would match on my-package
and not my-package/dist/my-package.js
.
In a file run the fix imports command. In my Vim, the cursor disappears until I try moving it again. This seems a bit awkward so it might be nice to find a way to prevent it from happening.
I think I've traced it down to this line where we run the eslint command in Importer:
out, err = Open3.capture3(command,
stdin_data: @editor.current_file_content)
but I'm not entirely sure why this has this side-effect.
This is a really minor annoyance, but I figured I'd log it here in case someone happens to know of an easy fix.
At Brigade we have recently switched from jshint/jsxhint to eslint, and it would be nice if this plugin worked with the eslint tool in the same way that it works with jshint/jsxhint.
...or maybe some other directory, as long as they are outside the root. The root directory is a little cluttered at the moment.
I find that whenever I modify the .importjs.json
file, I need to restart Vim before the new settings take effect. It would be nice if I the settings were just reloaded without needing to restart Vim.
If I have a section of require
d modules at the top that looks like this:
const MyModule = require('path/to/my_module');
const MyModuleThatHasALongName =
require('path/to/my_module_that_has_a_long_name');
const SomeModule = require('path/to/some_module');
import-js gets confused when adding a new module to the list:
const AnotherModule = require('path/to/another_module');
const MyModule = require('path/to/my_module');
const MyModuleThatHasALongName =
require('path/to/my_module_that_has_a_long_name');
const SomeModule = require('path/to/some_module');
where I would expect:
const AnotherModule = require('path/to/another_module');
const MyModule = require('path/to/my_module');
const MyModuleThatHasALongName =
require('path/to/my_module_that_has_a_long_name');
const SomeModule = require('path/to/some_module');
It would be nice if import-js worked better with this format.
Bonus points would be specifying a character limit (defaulted to 80
) that it would try to stay within when importing new dependencies.
We have people on our team who use Vim, Emacs, and Sublime Text. It seems like each of these editors could benefit from this functionality, so it might be nice to extract the core of this plugin into a standalone program that individual plugins for each editor could then depend on.
Currently, with aliases
configuration like the following:
"React": {
"path": "react",
"destructure": [
"PropTypes"
]
}
importing both React
and PropTypes
will result in:
import React from 'react';
import { PropTypes } from 'react';
but it would be better if it instead resulted in:
import React, { PropTypes } from 'react';
I'm not sure if there is any equivalent syntax for CommonJS imports, but it would be really nice if ImportJS did this when using the import
declaration keyword. I suppose if you were using CommonJS, it would be better to have one require
and one assignment after the fact than two require
s:
const React = require('react');
const { PropTypes } = React;
We need to update the gem available on rubygems to include the Emacs editor.
If you have a component like components/MyComponent/index.jsx
, you can require
the directory (i.e. require('components/MyComponent')
and it will default to the index. There is a table here that describes this behavior: http://webpack.github.io/docs/configuration.html#resolve-alias
It would be really great if import-js were able to match these directories.
Now that import-js has extracted the core into a standalone gem, it can be integrated more easily with additional editors. We already have emacs support (#61) and we should add sublime text support.
If you are using import-js in a project that uses npm, you might have a folder structure that looks like:
node_modules/package/node_modules/something_else/node_modules/another_thing/utils.js
However, you should never require
something that your app doesn't directly depend on, so it would be nice if anything in a nested node_modules
directory was simply excluded from import-js.
Perhaps import-js should have a notion of excluded patterns and allow people to specify whatever fits their app? e.g.
"exclude": [
"node_modules/**/node_modules"
]
Depending on Ruby makes the plug-in harder to install (trust me, I know...) and the Ruby bit is actually pretty small, so it might be worth porting it to vimscript.
If I am working on an app that uses JavaScript for the client side and Node.js for the server side, and I want to use ES2015 modules (ESM) import syntax on the client side, I am currently somewhat out of luck with import-js since Node.js doesn't yet support ESM and I don't really see it on their roadmap. For these cases, it would be nice if import-js had a way where I could use const
for my server code and import
for my client code.
One option would be to allow this to be configured in the .importjs.json
file. Another option would be to allow .importjs.json
files to be added wherever and then merged into the main configuration. I think this is the approach that ESLint takes, FWIW.
I'm not really sure if the juice is worth the squeeze here, but I figured I'd open this issue while I was thinking about it.
I run into this frequently now, since I use Sublime Text which only supports import_all. It would never recognise <Button>
as an unused variable.
Sometimes, when you're importing a module with a long name/path to, the Vim buffer width isn't big enough to display the full message. In those cases, you have to hit Enter in order to continue doing what you were doing in the file. We could fix this by looking at the width of the buffer and automatically truncating the log message.
I think that most times there are multiple matches, I want the first match. If import-js picked the first match in the priority order as defined in the configuration file, using the plugin would be a lot smoother. It could also stop searching after finding the first match which would make it faster in most cases.
In some projects I prefer to configure webpack to not automagically add the file extension (.js
or .jsx
) to require statements, and then when using import-js
I have to manually add it to the generated require
statement.
We could add a configuration setting for 'include_file_extensions' that would allow import-js
to leave the file extension as part of the require
path.
Let's say that you want to use a library that exports a single object that has a bunch of objects on it, but you want to just use those objects directly. It would be nice if import-js were able to be set up to allow for automatic destructuring.
For example, if I am using underscore, but instead of wanting to reference things like _.memoize()
and _.debounce()
I want to use memoize()
and debounce()
, it would be nice to be able to use import-js on the memoize()
function call to grab the dependency like this:
const { memoize } = require('underscore');
And if I trigger it again on another function call from the same package, it should add to the destructuring:
const { debounce, memoize } = require('underscore');
When i try to install import-js by gem it shows an error.
sudo gem install import-js
gem install import-js
ERROR: Could not find a valid gem 'import-js' (>= 0) in any repository
ERROR: Possible alternatives: import_js
So I tried sudo gem install import_js
ERROR: Error installing import_js:
slop requires Ruby version >= 2.0.0.
How can I solve this? I really want to use this :)
As I've been working to improve the Sublime plugin, I've enhanced the command-line interface to support more usecases. I've noticed that the Emacs plugin only supports a subset of the commands available:
The Sublime and vim plugins both support all of these commands:
They're also able to resolve variables that resolve to multiple js modules by bringing up a selection list to pick from.
I want import-js to be the same across the board, and it would be great if Emacs could catch up. @kevinkehl: would it make sense for the Emacs plugin to also use the command line tool? I know that it uses a buffer to send messages back and forth, but there might be some things there that could be simplified by using the cli tool instead. import-js
has since the first release been enhanced in a number of ways:
stderr
is used for messaging - it will contain a json string with messages
and ask_for_selections
keys.ask_for_selections
was in the json), you can rerun the command and pass in the selection using --selections foo:1,bar:3
.--goto
is passed in, the stdout
will contain a path to the file to open.--goto
can also be used together with --selections
.I'm happy to work on this if you don't have time/feel up for it @kevinkehl. But it would be good to hear your thoughts first.
In #114 I improved some error reporting that happens when packages that are expected by the local project's .eslintrc
file are not installed globally. It would be nice, however, if import-js preferred the locally installed eslint over the globally installed one, so it could just rely on these packages being installed locally.
Normally, to execute local node_modules binaries, I do something like $(npm bin)/executable
since npm bin
will output the path to the local node_modules/.bin
directory.
I was in a situation where I needed to import shared_config.json
(not shared_config
). If I add "SharedConfig": "shared_config.json"
to the aliases
configuration, I still get this when I import:
const SharedConfig = require('shared_config');
In this case the file ending is important (the import won't work withouth it).
When adding 'use strict';
to the top of a file to enable strict mode for the file, the 'use strict';
declaration must be at the top of the file. However, ImportJS puts its imports above this declaration, causing it to not work.
Since we are adding the ESLint control comment to the top of the file for detecting undefined variables
/* eslint no-unused-vars: [2, { "vars": "all", "args": "none" }] */
this will work well for regular variables. However, if you are using JSX and React, we need an additional option and access to the eslint-plugin-react plugin, since that plugin is responsible for finding reference errors for components. https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-undef.md
/* eslint react/jsx-no-undef: 2 */
When I try to use 'importJS' I have been seeing this error:
Error detected while processing /Users/paradasia/.vim/bundle/import-js/autoload/importjs.vim:
line 20:
SyntaxError: (eval):1:inrequire': /Users/paradasia/.vim/bundle/import-js/ruby/import-js/importer.rb:71: syntax error, unexpected '.', expecting kEND Error detected while processing function importjs#ImportJSImport: line 1: NoMethodError: undefined method
import' for nil:NilClass
Press ENTER or type command to continue
I'm going to look into it a bit and see if I can find the problem. Since this does not happen on my work laptop, I assume it is related to something in how my environment is set up.
It would be nice if import-js could be configured to produce import
syntax used by ES2015 modules.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
Wouldn't it be cool to configure your editor to run an import-cleanup task on save? Something that would find unused imports, and delete the ones not used. And potentially also import anything that's not been imported, but I can see that as a next step.
If you are using JSX, you need to import React even though the variable doesn't appear to be used. eslint-plugin-react has a rule that detects this for you, which we could piggyback off of.
This should probably be enabled (or disabled?) as an option, since some people might be defining React
as a global variable.
As seen in this code snippet, some projects prefer relative paths for non-node_modules modules:
import cheerio from 'cheerio';
import Sinon from 'sinon';
import ReactWrapper from './ReactWrapper';
import ShallowWrapper from './ShallowWrapper';
import { onPrototype } from './Utils';
import { renderToStaticMarkup } from './react-compat';
It would be nice if ImportJS was able to support this.
The ImportJS package in Package Control is only available to OSX users. I choose to make that limitation because I don't have a Linux or Windows environment available to test things in at the moment.
@janpaul123, @shreeya, @kevinkehl, @lencioni: Does anyone have another environment than OSX where they would be willing to test import-js? I'd mainly like to see how the Sublime plugin works, but I guess it would be good to test the Emacs and vim plugins too if possible.
Now that import-js has extracted the core into a standalone gem, it can be integrated more easily with additional editors. We already have emacs and Sublime Text support and we should add WebStorm support. https://plugins.jetbrains.com/webStorm
In a recent JS survey, WebStorm was one of the most popular editors for JS developers: https://ponyfoo.com/articles/javascript-developer-survey-results#what-are-your-preferred-text-editors
My vim wasn't picking up changes I made in the local import-js project. As part of autoloading the vim plugin, require 'import_js'
is run, and that will pick up any installed gems before the code in the lib
folder.
As lines get longer, it would probably make sense for destructuring to be broken out into one variable per line, such as seen in the following code snippet:
import React from 'react';
import { flatten, unique, compact } from 'underscore';
import cheerio from 'cheerio';
import {
nodeEqual,
propFromEvent,
withSetStateAllowed,
propsOfNode,
} from './Utils';
import {
debugNodes,
} from './Debug';
import {
getTextFromNode,
hasClassName,
childrenOfNode,
parentsOfNode,
treeFilter,
buildPredicate,
} from './ShallowTraversal';
import {
createShallowRenderer,
renderToStaticMarkup,
} from './react-compat';
When working on a module I sometimes end up removing all references to a module that I had previously depended on. It would be nice if import-js could automatically remove the require statements for these for me similar to how it can add all missing modules by running :ImportJSImportAll
.
I think importing and removing could be implemented as separate commands, and a third command could be added to do both at the same time--like an auto cleanup imports command. Or, if you don't see the value in keeping them separate, just roll it all into one command.
With this feature, it might work really well to automatically run this when saving .js files with something like:
autocmd BufWritePre *.js :ImportJSAutoFix
Then I could simply stop thinking about managing this bit of code in every file, freeing up my mind to think about more important things.
Many Vim plugins are prefixed with vim-
, which I think helps people find the plugins, understand what they are used for, and prevents naming collisions. I think it might be worth considering renaming this to vim-import-js
, unless you plan on expanding it to support other editors, like Sublime. What do you think?
It would be great if I could specify a character limit (defaulted to 80) that import-js would try to stay within when importing new dependencies.
So instead of import-js generating this:
const MyModule = require('path/to/my_module');
const MyModuleThatHasALongName = require('path/to/my_module_that_has_a_long_name');
it would generate this:
const MyModule = require('path/to/my_module');
const MyModuleThatHasALongName =
require('path/to/my_module_that_has_a_long_name');
This is similar to #9.
ES2015 modules (ESM) is the future and we can embrace this by changing the default declaration keyword from var
to import
. What do you say?
It seems like import-js
doesn't find files if they use dashed or camel-cased filenames. My first thought is that by default it should look for all matching filenames that are either snake-cased, dashed, or camel cased, and users can configure it to only use one if they prefer. That way the default works for everyone, no configuration required.
The alternative would be to pick one as the default and allow users to configure it to use one or more of the other patterns.
I am working in a large project where I am trying to get import-js set up for the first time. In this project we have moment
in our package.json
file and I'd like to import it into a new module. However, when matching modules, import-js presents me with a list like the following:
ImportJS: Pick JS module to import for 'moment':
1: moment (main: ./moment.js)
2: node_modules/some-package/node_modules/convict/node_modules/moment (main: ./moment.js)
3: node_modules/some-package/node_modules/convict/node_modules/moment/moment
4: node_modules/some-package/node_modules/convict/node_modules/moment/package
5: node_modules/casual/node_modules/moment (main: ./moment.js)
6: node_modules/casual/node_modules/moment/moment
7: node_modules/casual/node_modules/moment/package
8: node_modules/moment (main: ./moment.js)
9: node_modules/moment/moment
10: node_modules/moment/package
Perhaps my memory is failing me, but I expected this to resolve to just one module, which happens to be the first on this list (see e237f86).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.