import_js 0.2.5 → 0.3.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: 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