import_js 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/import_js/configuration.rb +5 -5
- data/lib/import_js/emacs_editor.rb +3 -3
- data/lib/import_js/import_statement.rb +3 -3
- data/lib/import_js/importer.rb +54 -16
- data/lib/import_js/js_module.rb +56 -11
- data/lib/import_js/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3808c953be3c8a47d0212d952f35b4329774cba8
|
4
|
+
data.tar.gz: f1929ccab0f99004521babc2dbbf8d35347c7313
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9380c3f44a4306a0e9d843496bf846c47200e696649a88348135e9c7f1d928e04ad5520d67a7c15beb3306e02af1ad7aa2fd2aaaef983c0eec2463e6ca9fd288
|
7
|
+
data.tar.gz: cc46051020022e9e7ba9db5b4c8750b104ad372bb72442f5fb7712867084f8bfff92f9dcba06826ca77d87a42d4897dfe72b5b96b7fb89f7dcb61d804e684f75
|
@@ -57,7 +57,7 @@ module ImportJS
|
|
57
57
|
path = path.sub(/\{filename\}/,
|
58
58
|
File.basename(path_to_current_file, '.*'))
|
59
59
|
end
|
60
|
-
|
60
|
+
JSModule.new(import_path: path)
|
61
61
|
end
|
62
62
|
|
63
63
|
# @param variable_name [String]
|
@@ -66,7 +66,7 @@ module ImportJS
|
|
66
66
|
get('named_exports').each do |import_path, named_exports|
|
67
67
|
next unless named_exports.include?(variable_name)
|
68
68
|
|
69
|
-
js_module =
|
69
|
+
js_module = JSModule.new(import_path: import_path)
|
70
70
|
js_module.has_named_exports = true
|
71
71
|
return js_module
|
72
72
|
end
|
@@ -108,11 +108,11 @@ module ImportJS
|
|
108
108
|
def check_current_version!
|
109
109
|
minimum_version = get('minimum_version')
|
110
110
|
return if Gem::Dependency.new('', ">= #{minimum_version}")
|
111
|
-
.match?('',
|
111
|
+
.match?('', VERSION)
|
112
112
|
|
113
|
-
fail
|
113
|
+
fail ClientTooOldError,
|
114
114
|
'The .importjs.json file you are using requires version ' \
|
115
|
-
"#{get('minimum_version')}. You are using #{
|
115
|
+
"#{get('minimum_version')}. You are using #{VERSION}."
|
116
116
|
end
|
117
117
|
end
|
118
118
|
end
|
@@ -16,13 +16,13 @@ module ImportJS
|
|
16
16
|
|
17
17
|
case command
|
18
18
|
when 'import'
|
19
|
-
|
19
|
+
Importer.new(self).import
|
20
20
|
write_file
|
21
21
|
puts 'import:success'
|
22
22
|
when 'goto'
|
23
|
-
|
23
|
+
Importer.new(self).goto
|
24
24
|
when 'fix'
|
25
|
-
|
25
|
+
Importer.new(self).fix_imports
|
26
26
|
write_file
|
27
27
|
puts 'import:success'
|
28
28
|
else
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ImportJS
|
2
2
|
# Class that represents an import statement, e.g.
|
3
3
|
# `const foo = require('foo');`
|
4
|
-
# `
|
4
|
+
# `var foo = myCustomRequire('foo');`
|
5
5
|
# `import foo from 'foo';`
|
6
6
|
class ImportStatement
|
7
7
|
REGEX_CONST_LET_VAR = /
|
@@ -50,7 +50,7 @@ module ImportJS
|
|
50
50
|
|
51
51
|
# @param string [String] a possible import statement, e.g.
|
52
52
|
# `const foo = require('foo');`
|
53
|
-
# `
|
53
|
+
# `var foo = myCustomRequire('foo');`
|
54
54
|
# `import foo from 'foo';`
|
55
55
|
# @return [ImportJS::ImportStatement?] a parsed statement, or nil if the
|
56
56
|
# string can't be parsed
|
@@ -138,7 +138,7 @@ module ImportJS
|
|
138
138
|
else
|
139
139
|
[default_import_string(max_line_length, tab)]
|
140
140
|
end
|
141
|
-
else # const/
|
141
|
+
else # const/var
|
142
142
|
strings = []
|
143
143
|
|
144
144
|
if default_import
|
data/lib/import_js/importer.rb
CHANGED
@@ -9,14 +9,14 @@ module ImportJS
|
|
9
9
|
REGEX_MULTI_LINE_COMMENT_END = %r{\*/}
|
10
10
|
REGEX_WHITESPACE_ONLY = /\A\s*\Z/
|
11
11
|
|
12
|
-
def initialize(editor =
|
12
|
+
def initialize(editor = VIMEditor.new)
|
13
13
|
@editor = editor
|
14
14
|
end
|
15
15
|
|
16
16
|
# Finds variable under the cursor to import. By default, this is bound to
|
17
17
|
# `<Leader>j`.
|
18
18
|
def import
|
19
|
-
|
19
|
+
reload_config
|
20
20
|
variable_name = @editor.current_word
|
21
21
|
if variable_name.empty?
|
22
22
|
message(<<-EOS.split.join(' '))
|
@@ -39,17 +39,29 @@ module ImportJS
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def goto
|
42
|
-
|
42
|
+
reload_config
|
43
43
|
js_modules = []
|
44
44
|
variable_name = @editor.current_word
|
45
45
|
time do
|
46
46
|
js_modules = find_js_modules(variable_name)
|
47
47
|
end
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
|
49
|
+
if js_modules.empty?
|
50
|
+
# No JS modules are found for the variable, so there is nothing to go to
|
51
|
+
# and we return early.
|
52
|
+
return message("No modules were found for `#{variable_name}`")
|
53
|
+
end
|
54
|
+
|
55
|
+
js_module = resolve_goto_module(js_modules, variable_name)
|
56
|
+
|
57
|
+
unless js_module
|
58
|
+
# The current word is not mappable to one of the JS modules that we
|
59
|
+
# found. This can happen if the user does not select one from the list.
|
60
|
+
# We have nothing to go to, so we return early.
|
61
|
+
return message("Could not resolve a module for `#{variable_name}`")
|
52
62
|
end
|
63
|
+
|
64
|
+
@editor.open_file(js_module.open_file_path(@editor.path_to_current_file))
|
53
65
|
end
|
54
66
|
|
55
67
|
REGEX_ESLINT_RESULT = /
|
@@ -68,7 +80,7 @@ module ImportJS
|
|
68
80
|
|
69
81
|
# Removes unused imports and adds imports for undefined variables
|
70
82
|
def fix_imports
|
71
|
-
|
83
|
+
reload_config
|
72
84
|
eslint_result = run_eslint_command
|
73
85
|
|
74
86
|
unused_variables = []
|
@@ -107,6 +119,13 @@ module ImportJS
|
|
107
119
|
|
108
120
|
private
|
109
121
|
|
122
|
+
# The configuration is relative to the current file, so we need to make sure
|
123
|
+
# that we are operating with the appropriate configuration when we perform
|
124
|
+
# certain actions.
|
125
|
+
def reload_config
|
126
|
+
@config = Configuration.new(@editor.path_to_current_file)
|
127
|
+
end
|
128
|
+
|
110
129
|
def message(str)
|
111
130
|
@editor.message("ImportJS: #{str}")
|
112
131
|
end
|
@@ -139,11 +158,11 @@ module ImportJS
|
|
139
158
|
stdin_data: @editor.current_file_content)
|
140
159
|
|
141
160
|
if ESLINT_STDOUT_ERROR_REGEXES.any? { |regex| out =~ regex }
|
142
|
-
fail
|
161
|
+
fail ParseError.new, out
|
143
162
|
end
|
144
163
|
|
145
164
|
if ESLINT_STDERR_ERROR_REGEXES.any? { |regex| err =~ regex }
|
146
|
-
fail
|
165
|
+
fail ParseError.new, err
|
147
166
|
end
|
148
167
|
|
149
168
|
out.split("\n")
|
@@ -296,7 +315,7 @@ module ImportJS
|
|
296
315
|
# iterate through those and stop at anything that's not an import.
|
297
316
|
imports = {}
|
298
317
|
potential_imports_blob.scan(/^.*?;/m).each do |potential_import|
|
299
|
-
import_statement =
|
318
|
+
import_statement = ImportStatement.parse(potential_import)
|
300
319
|
break unless import_statement
|
301
320
|
|
302
321
|
if imports[import_statement.path]
|
@@ -333,7 +352,7 @@ module ImportJS
|
|
333
352
|
if lookup_path == ''
|
334
353
|
# If lookup_path is an empty string, the `find` command will not work
|
335
354
|
# as desired so we bail early.
|
336
|
-
fail
|
355
|
+
fail FindError.new,
|
337
356
|
"lookup path cannot be empty (#{lookup_path.inspect})"
|
338
357
|
end
|
339
358
|
|
@@ -345,14 +364,14 @@ module ImportJS
|
|
345
364
|
command = "#{find_command} | #{egrep_command}"
|
346
365
|
out, err = Open3.capture3(command)
|
347
366
|
|
348
|
-
fail
|
367
|
+
fail FindError.new, err unless err == ''
|
349
368
|
|
350
369
|
matched_modules.concat(
|
351
370
|
out.split("\n").map do |f|
|
352
371
|
next if @config.get('excludes').any? do |glob_pattern|
|
353
372
|
File.fnmatch(glob_pattern, f)
|
354
373
|
end
|
355
|
-
|
374
|
+
JSModule.construct(
|
356
375
|
lookup_path: lookup_path,
|
357
376
|
relative_file_path: f,
|
358
377
|
strip_file_extensions:
|
@@ -376,7 +395,7 @@ module ImportJS
|
|
376
395
|
@config.package_dependencies.each do |dep|
|
377
396
|
next unless dep =~ dep_regex
|
378
397
|
|
379
|
-
js_module =
|
398
|
+
js_module = JSModule.construct(
|
380
399
|
lookup_path: 'node_modules',
|
381
400
|
relative_file_path: "node_modules/#{dep}/package.json",
|
382
401
|
strip_file_extensions: [])
|
@@ -399,7 +418,7 @@ module ImportJS
|
|
399
418
|
|
400
419
|
# @param js_modules [Array]
|
401
420
|
# @param variable_name [String]
|
402
|
-
# @return [
|
421
|
+
# @return [ImportJS::JSModule]
|
403
422
|
def resolve_one_js_module(js_modules, variable_name)
|
404
423
|
if js_modules.length == 1
|
405
424
|
js_module = js_modules.first
|
@@ -421,6 +440,25 @@ module ImportJS
|
|
421
440
|
js_modules[selected_index]
|
422
441
|
end
|
423
442
|
|
443
|
+
# @param js_modules [Array]
|
444
|
+
# @param variable_name [String]
|
445
|
+
# @return [ImportJS::JSModule]
|
446
|
+
def resolve_goto_module(js_modules, variable_name)
|
447
|
+
return js_modules.first if js_modules.length == 1
|
448
|
+
|
449
|
+
# Look for a current import matching the goto
|
450
|
+
find_current_imports[:imports].each do |ist|
|
451
|
+
js_modules.each do |js_module|
|
452
|
+
next unless variable_name == ist.default_import ||
|
453
|
+
(ist.named_imports || []).include?(variable_name)
|
454
|
+
return js_module if ist.path == js_module.import_path
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
# Fall back to asking the user to resolve the ambiguity
|
459
|
+
resolve_one_js_module(js_modules, variable_name)
|
460
|
+
end
|
461
|
+
|
424
462
|
# Takes a string in any of the following four formats:
|
425
463
|
# dash-separated
|
426
464
|
# snake_case
|
data/lib/import_js/js_module.rb
CHANGED
@@ -52,10 +52,28 @@ module ImportJS
|
|
52
52
|
# @return [String, String]
|
53
53
|
def self.resolve_import_path_and_main(file_path, strip_file_extensions)
|
54
54
|
if file_path.end_with? '/package.json'
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
return
|
55
|
+
return [nil, nil] unless File.exist?(file_path)
|
56
|
+
|
57
|
+
file_contents = File.read(file_path)
|
58
|
+
return [nil, nil] if file_contents.strip.empty?
|
59
|
+
|
60
|
+
main_file = JSON.parse(file_contents)['main']
|
61
|
+
match = file_path.match(%r{(?<package>.*)/package\.json})
|
62
|
+
|
63
|
+
unless main_file
|
64
|
+
index_file = find_index(match[:package])
|
65
|
+
return [nil, nil] unless index_file
|
66
|
+
main_file = index_file
|
67
|
+
end
|
68
|
+
|
69
|
+
if File.directory?("#{match[:package]}/#{main_file}")
|
70
|
+
# The main in package.json refers to a directory, so we want to
|
71
|
+
# resolve it to an index file.
|
72
|
+
index_file = find_index("#{match[:package]}/#{main_file}")
|
73
|
+
main_file += "/#{index_file}" if index_file
|
74
|
+
end
|
75
|
+
|
76
|
+
return match[:package], main_file
|
59
77
|
end
|
60
78
|
|
61
79
|
match = file_path.match(%r{(.*)/(index\.js[^/]*)$})
|
@@ -66,6 +84,15 @@ module ImportJS
|
|
66
84
|
[import_path, nil]
|
67
85
|
end
|
68
86
|
|
87
|
+
# @param directory [String]
|
88
|
+
# @return [String, nil]
|
89
|
+
def self.find_index(directory)
|
90
|
+
%w[index.js index.jsx].each do |index_file|
|
91
|
+
return index_file if File.exist? "#{directory}/#{index_file}"
|
92
|
+
end
|
93
|
+
nil
|
94
|
+
end
|
95
|
+
|
69
96
|
# @param import_path [String]
|
70
97
|
def initialize(import_path: nil)
|
71
98
|
self.import_path = import_path
|
@@ -110,23 +137,41 @@ module ImportJS
|
|
110
137
|
# @param path_to_current_file [String]
|
111
138
|
# @return [String]
|
112
139
|
def open_file_path(path_to_current_file)
|
113
|
-
if file_path
|
114
|
-
|
140
|
+
if @file_path
|
141
|
+
# There is a file_path. This happens for JSModules that are not aliases.
|
142
|
+
return @file_path unless @file_path.end_with?('/package.json')
|
143
|
+
|
144
|
+
# The file_path points to a package.json file, so we want to look in
|
145
|
+
# that package.json file for a `main` configuration value and open that
|
146
|
+
# file instead.
|
147
|
+
return @file_path.sub(/package\.json$/, main_file)
|
115
148
|
end
|
116
|
-
return file_path if file_path
|
117
149
|
|
118
|
-
|
119
|
-
|
150
|
+
# There is no file_path. This likely means that we are working with an
|
151
|
+
# alias, so we want to expand it to a full path if we can.
|
152
|
+
|
153
|
+
if @import_path.start_with?('.')
|
154
|
+
# The import path in the alias starts with a ".", which means that it is
|
155
|
+
# relative to the current file. In order to open this file, we need to
|
156
|
+
# expand it to a full path.
|
157
|
+
return File.expand_path(
|
158
|
+
@import_path, File.dirname(path_to_current_file))
|
120
159
|
end
|
121
160
|
|
122
|
-
|
161
|
+
# This is likely an alias that points to a package, so let's try to find
|
162
|
+
# its main file from its package.json file.
|
163
|
+
file_path = "node_modules/#{@import_path}/package.json"
|
164
|
+
_, main = self.class.resolve_import_path_and_main(file_path, [])
|
165
|
+
return "node_modules/#{@import_path}/#{main}" if main
|
166
|
+
|
167
|
+
@import_path
|
123
168
|
end
|
124
169
|
|
125
170
|
# @param variable_name [String]
|
126
171
|
# @param config [ImportJS::Configuration]
|
127
172
|
# @return [ImportJS::ImportStatement]
|
128
173
|
def to_import_statement(variable_name, config)
|
129
|
-
|
174
|
+
ImportStatement.new.tap do |statement|
|
130
175
|
if has_named_exports
|
131
176
|
statement.inject_named_import(variable_name)
|
132
177
|
else
|
data/lib/import_js/version.rb
CHANGED