import_js 0.2.5 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b5855fcda8dcbe929e0aecbd16b9b940cb6fa80a
4
- data.tar.gz: 458cbb3e52b3358ec99b5c8891f9ae54b06769b9
3
+ metadata.gz: c90724e922f7ebecab12977097f1b867d83d8f74
4
+ data.tar.gz: 43cc4828550165c17ca8b07b142c5e033fbbb31f
5
5
  SHA512:
6
- metadata.gz: e4a57078bbd9ebf4a07fe2f09c6e666fcd118f223c8ac35d54ca8538648a5d920f5ed7883170d905bf40a96969a74aae46aa4b4fc4d424f1451fcae6a0b82f10
7
- data.tar.gz: 2722de373880d2530db9eb769543248dc341067fba8cf7791ddac1fc5380cd9fde64b548fc0fbcc8e0d5ea0f51938758da8a4ec62d8c2d7c8a2b4847e0a8c2a7
6
+ metadata.gz: c6f3b02306c7c21ccc09b13e7246d2c8ddb7c78f05f149d2644b73d1ce8d731d4349e54f68d52bc79b1558d07aa94aba5fe7a809f9f4137410f9cfccd0d4225e
7
+ data.tar.gz: 105ab5859eaef7bd8d3bd5b31a0725c4000cf833743a786c7d6a1e9a5bac21bcbdc2de79580c565f74fde07a58f4467b004709031695a892d3468d4cc9304b2d
@@ -6,10 +6,13 @@ module ImportJS
6
6
 
7
7
  DEFAULT_CONFIG = {
8
8
  'aliases' => {},
9
- 'declaration_keyword' => 'var',
9
+ 'declaration_keyword' => 'import',
10
+ 'eslint_executable' => 'eslint',
10
11
  'excludes' => [],
12
+ 'ignore_package_prefixes' => [],
11
13
  'lookup_paths' => ['.'],
12
- 'strip_file_extensions' => ['.js', '.jsx']
14
+ 'strip_file_extensions' => ['.js', '.jsx'],
15
+ 'use_relative_paths' => false
13
16
  }
14
17
 
15
18
  # Class that initializes configuration from a .importjs.json file
@@ -41,14 +44,18 @@ module ImportJS
41
44
  path = path.sub(/\{filename\}/,
42
45
  File.basename(path_to_current_file, '.*'))
43
46
  end
44
- ImportJS::JSModule.new(nil, path, [])
47
+ ImportJS::JSModule.new(lookup_path: nil,
48
+ relative_file_path: path,
49
+ strip_file_extensions: [])
45
50
  end
46
51
 
47
52
  def resolve_destructured_alias(variable_name)
48
53
  @config['aliases'].each do |_, path|
49
54
  next if path.is_a? String
50
55
  if (path['destructure'] || []).include?(variable_name)
51
- js_module = ImportJS::JSModule.new(nil, path['path'], [])
56
+ js_module = ImportJS::JSModule.new(lookup_path: nil,
57
+ relative_file_path: path['path'],
58
+ strip_file_extensions: [])
52
59
  js_module.is_destructured = true
53
60
  return js_module
54
61
  end
@@ -36,7 +36,7 @@ module ImportJS
36
36
  (?<destructured>.*) # <destructured> variables
37
37
  \s*
38
38
  \}
39
- }x
39
+ }xm
40
40
 
41
41
  attr_accessor :assignment
42
42
  attr_accessor :original_import_string # a cache of the parsed import string
@@ -90,8 +90,7 @@ module ImportJS
90
90
 
91
91
  # @return [Array<String>] the output from eslint, line by line
92
92
  def run_eslint_command
93
- command = %w[
94
- eslint
93
+ command = @config.get('eslint_executable') + ' ' + %w[
95
94
  --stdin
96
95
  --format unix
97
96
  --rule 'no-undef: 2'
@@ -101,12 +100,16 @@ module ImportJS
101
100
  stdin_data: @editor.current_file_content)
102
101
 
103
102
  if out =~ /Parsing error: / ||
104
- out =~ /Unrecoverable syntax error/
103
+ out =~ /Unrecoverable syntax error/ ||
104
+ out =~ /<text>:0:0: Cannot find module '.*'/
105
105
  fail ImportJS::ParseError.new, out
106
106
  end
107
107
 
108
108
  if err =~ /SyntaxError: / ||
109
- err =~ /eslint: command not found/
109
+ err =~ /eslint: command not found/ ||
110
+ err =~ /Cannot read config package: / ||
111
+ err =~ /Cannot find module '.*'/ ||
112
+ err =~ /No such file or directory/
110
113
  fail ImportJS::ParseError.new, err
111
114
  end
112
115
 
@@ -167,6 +170,17 @@ module ImportJS
167
170
  @editor.tab)
168
171
  end.flatten.sort
169
172
 
173
+ # Find old import strings so we can compare with the new import strings
174
+ # and see if anything has changed.
175
+ old_import_strings = []
176
+ old_imports_lines.times do |line|
177
+ old_import_strings << @editor.read_line(1 + line + imports_start_at)
178
+ end
179
+
180
+ # If nothing has changed, bail to prevent unnecessarily dirtying the
181
+ # buffer.
182
+ return if import_strings == old_import_strings
183
+
170
184
  # Delete old imports, then add the modified list back in.
171
185
  old_imports_lines.times { @editor.delete_line(1 + imports_start_at) }
172
186
  import_strings.reverse_each do |import_string|
@@ -227,16 +241,20 @@ module ImportJS
227
241
  # @param variable_name [String]
228
242
  # @return [Array]
229
243
  def find_js_modules(variable_name)
244
+ path_to_current_file = @editor.path_to_current_file
230
245
  if alias_module = @config.resolve_alias(variable_name,
231
- @editor.path_to_current_file)
246
+ path_to_current_file)
232
247
  return [alias_module]
233
248
  end
234
-
235
249
  egrep_command =
236
250
  "egrep -i \"(/|^)#{formatted_to_regex(variable_name)}(/index)?(/package)?\.js.*\""
237
251
  matched_modules = []
238
252
  @config.get('lookup_paths').each do |lookup_path|
239
- find_command = "find #{lookup_path} -name \"**.js*\""
253
+ find_command = %W[
254
+ find #{lookup_path}
255
+ -name "**.js*"
256
+ -not -path "./node_modules/*"
257
+ ].join(' ')
240
258
  out, _ = Open3.capture3("#{find_command} | #{egrep_command}")
241
259
  matched_modules.concat(
242
260
  out.split("\n").map do |f|
@@ -244,7 +262,13 @@ module ImportJS
244
262
  File.fnmatch(glob_pattern, f)
245
263
  end
246
264
  js_module = ImportJS::JSModule.new(
247
- lookup_path, f, @config.get('strip_file_extensions'))
265
+ lookup_path: lookup_path,
266
+ relative_file_path: f,
267
+ strip_file_extensions: @config.get('strip_file_extensions'),
268
+ make_relative_to: @config.get('use_relative_paths') &&
269
+ path_to_current_file
270
+ )
271
+
248
272
  next if js_module.skip
249
273
  js_module
250
274
  end.compact
@@ -253,11 +277,19 @@ module ImportJS
253
277
 
254
278
  # Find imports from package.json
255
279
  @config.package_dependencies.each do |dep|
256
- next unless dep =~ /^#{formatted_to_regex(variable_name)}$/
257
- js_module = ImportJS::JSModule.new(
258
- 'node_modules', "node_modules/#{dep}/package.json", [])
259
- next if js_module.skip
260
- matched_modules << js_module
280
+ ignore_prefixes = @config.get('ignore_package_prefixes')
281
+ dep_matcher = /^#{formatted_to_regex(variable_name)}$/
282
+ if dep =~ dep_matcher ||
283
+ ignore_prefixes.any? do |prefix|
284
+ dep.sub(/^#{prefix}/, '') =~ dep_matcher
285
+ end
286
+ js_module = ImportJS::JSModule.new(
287
+ lookup_path: 'node_modules',
288
+ relative_file_path: "node_modules/#{dep}/package.json",
289
+ strip_file_extensions: [])
290
+ next if js_module.skip
291
+ matched_modules << js_module
292
+ end
261
293
  end
262
294
 
263
295
  # If you have overlapping lookup paths, you might end up seeing the same
@@ -302,10 +334,26 @@ module ImportJS
302
334
  def formatted_to_regex(string)
303
335
  # Based on
304
336
  # http://stackoverflow.com/questions/1509915/converting-camel-case-to-underscore-case-in-ruby
305
- string.
306
- gsub(/([a-z\d])([A-Z])/, '\1.?\2'). # separates camelCase words with '.?'
307
- tr('-_', '.'). # replaces underscores or dashes with '.'
308
- downcase # converts all upper to lower case
337
+
338
+ # The pattern to match in between words. The "es" and "s" match is there
339
+ # to catch pluralized folder names. There is a risk that this is overly
340
+ # aggressive and will lead to trouble down the line. In that case, we can
341
+ # consider adding a configuration option to control mapping a singular
342
+ # variable name to a plural folder name (suggested by @lencioni in #127).
343
+ # E.g.
344
+ #
345
+ # {
346
+ # "^mock": "./mocks/"
347
+ # }
348
+ split_pattern = '(es|s)?.?'
349
+
350
+ # Split up the string, allow pluralizing and a single (any) character
351
+ # in between. This will make e.g. 'fooBar' match 'foos/bar', 'foo_bar',
352
+ # and 'foobar'.
353
+ string
354
+ .gsub(/([a-z\d])([A-Z])/, '\1' + split_pattern + '\2') # camelCase
355
+ .tr('-_', split_pattern)
356
+ .downcase
309
357
  end
310
358
 
311
359
  # @return [String]
@@ -1,3 +1,5 @@
1
+ require 'pathname'
2
+
1
3
  module ImportJS
2
4
  # Class that represents a js module found in the file system
3
5
  class JSModule
@@ -13,15 +15,25 @@ module ImportJS
13
15
  # the project root.
14
16
  # @param strip_file_extensions [Array] a list of file extensions to strip,
15
17
  # e.g. ['.js', '.jsx']
16
- def initialize(lookup_path, relative_file_path, strip_file_extensions)
18
+ # @param make_relative_to [String|nil] a path to a different file which the
19
+ # resulting import path should be relative to.
20
+ def initialize(lookup_path: nil,
21
+ relative_file_path: nil,
22
+ strip_file_extensions: nil,
23
+ make_relative_to: nil)
17
24
  @lookup_path = lookup_path
18
25
  @file_path = relative_file_path
26
+
27
+ if @lookup_path && @lookup_path.start_with?('.')
28
+ @lookup_path.sub!(/^\.\/?/, '')
29
+ @file_path.sub!(/^\.\/?/, '')
30
+ end
19
31
  if relative_file_path.end_with? '/package.json'
20
32
  @main_file = JSON.parse(File.read(relative_file_path))['main']
21
33
  match = relative_file_path.match(/(.*)\/package\.json/)
22
34
  @import_path = match[1]
23
35
  @skip = !@main_file
24
- elsif relative_file_path.match(/\/index\.js.*$/)
36
+ elsif relative_file_path.match(%r{/index\.js[^/]*$})
25
37
  match = relative_file_path.match(/(.*)\/(index\.js.*)/)
26
38
  @main_file = match[2]
27
39
  @import_path = match[1]
@@ -35,9 +47,34 @@ module ImportJS
35
47
  end
36
48
  end
37
49
 
38
- if lookup_path
39
- @import_path = @import_path.sub("#{@lookup_path}\/", '') # remove path prefix
50
+ if @lookup_path
51
+ @import_path.sub!(/^#{Regexp.escape(@lookup_path)}\//, '')
52
+ if make_relative_to
53
+ make_import_path_relative_to(make_relative_to)
54
+ end
55
+ end
56
+ end
57
+
58
+ # @param make_relative_to [String]
59
+ def make_import_path_relative_to(make_relative_to)
60
+ # First, strip out any absolute path up until the current directory
61
+ make_relative_to = make_relative_to.sub(Dir.pwd + "\/", '')
62
+
63
+ # Ignore if the file to relate to is part of a different lookup_path
64
+ return unless make_relative_to.start_with? @lookup_path
65
+
66
+ # Strip out the lookup_path
67
+ make_relative_to.sub!(/^#{Regexp.escape(@lookup_path)}\//, '')
68
+
69
+ path = Pathname.new(@import_path).relative_path_from(
70
+ Pathname.new(File.dirname(make_relative_to))
71
+ ).to_s
72
+
73
+ unless path.start_with?('.')
74
+ # `Pathname.relative_path_from` will not add "./" automatically
75
+ path = './' + path
40
76
  end
77
+ @import_path = path
41
78
  end
42
79
 
43
80
  # @return [String] a readable description of the module
@@ -1,4 +1,4 @@
1
1
  # Defines the gem version.
2
2
  module ImportJS
3
- VERSION = '0.2.5'
3
+ VERSION = '0.3.1'
4
4
  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.2.5
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henric Trotzig