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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a2a0036427b0f66373fcbc6fda702570d501f281
4
- data.tar.gz: 9c798047e26eb9189e169c5395ed1bd41b03e2fc
3
+ metadata.gz: 3808c953be3c8a47d0212d952f35b4329774cba8
4
+ data.tar.gz: f1929ccab0f99004521babc2dbbf8d35347c7313
5
5
  SHA512:
6
- metadata.gz: 4eaed3ab7c8204e62a7b19bdad9cf002384f6797cd15fe6f6615763ebcda6f8cf607cbb3127f8c494082a53f84684c17e383544f897cd368ae0074101676dc5d
7
- data.tar.gz: 43c8abdad3178c4df5c6f04a7030737daa9d2cb4e83cb777e6dbde088a5a43dffa2690ae13e1b1950ce915dc01f5252a75d4747883a9d0777124cf7353541e64
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
- ImportJS::JSModule.new(import_path: path)
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 = ImportJS::JSModule.new(import_path: import_path)
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?('', ImportJS::VERSION)
111
+ .match?('', VERSION)
112
112
 
113
- fail ImportJS::ClientTooOldError,
113
+ fail ClientTooOldError,
114
114
  'The .importjs.json file you are using requires version ' \
115
- "#{get('minimum_version')}. You are using #{ImportJS::VERSION}."
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
- ImportJS::Importer.new(self).import
19
+ Importer.new(self).import
20
20
  write_file
21
21
  puts 'import:success'
22
22
  when 'goto'
23
- ImportJS::Importer.new(self).goto
23
+ Importer.new(self).goto
24
24
  when 'fix'
25
- ImportJS::Importer.new(self).fix_imports
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
- # `let foo = myCustomRequire('foo');`
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
- # `let foo = myCustomRequire('foo');`
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/let/var
141
+ else # const/var
142
142
  strings = []
143
143
 
144
144
  if default_import
@@ -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 = ImportJS::VIMEditor.new)
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
- @config = ImportJS::Configuration.new(@editor.path_to_current_file)
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
- @config = ImportJS::Configuration.new(@editor.path_to_current_file)
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
- return if js_modules.empty?
49
- js_module = resolve_one_js_module(js_modules, variable_name)
50
- if js_module
51
- @editor.open_file(js_module.open_file_path(@editor.path_to_current_file))
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
- @config = ImportJS::Configuration.new(@editor.path_to_current_file)
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 ImportJS::ParseError.new, out
161
+ fail ParseError.new, out
143
162
  end
144
163
 
145
164
  if ESLINT_STDERR_ERROR_REGEXES.any? { |regex| err =~ regex }
146
- fail ImportJS::ParseError.new, err
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 = ImportJS::ImportStatement.parse(potential_import)
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 ImportJS::FindError.new,
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 ImportJS::FindError.new, err unless err == ''
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
- ImportJS::JSModule.construct(
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 = ImportJS::JSModule.construct(
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 [String]
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
@@ -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
- main_file = JSON.parse(File.read(file_path))['main']
56
- return [nil, nil] unless main_file
57
- match = file_path.match(%r{(.*)/package\.json})
58
- return match[1], main_file
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 && file_path.end_with?('/package.json')
114
- return file_path.sub(/package\.json$/, main_file)
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
- if import_path.start_with?('.')
119
- return File.expand_path(import_path, File.dirname(path_to_current_file))
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
- import_path
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
- ImportJS::ImportStatement.new.tap do |statement|
174
+ ImportStatement.new.tap do |statement|
130
175
  if has_named_exports
131
176
  statement.inject_named_import(variable_name)
132
177
  else
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Defines the gem version.
4
4
  module ImportJS
5
- VERSION = '0.4.0'.freeze
5
+ VERSION = '0.4.1'.freeze
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: import_js
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henric Trotzig