import_js 0.0.2 → 0.0.3

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: 80847dd047d3098f2375708a53acbe8fe3b788d3
4
- data.tar.gz: 63db9742a0a4bdb87b019020cf1f20a2fb8f82dd
3
+ metadata.gz: 3b23358bb0d61ef8fac8b2e8789f2bfffa092fb9
4
+ data.tar.gz: 132643d9f5029de7cf5087d496fedb91e53d903b
5
5
  SHA512:
6
- metadata.gz: 1c6631a83e5bc9498db3d1c39a41c5f56df7e2a032b1624a7aa4b3d64b6215cb9990369bec4bbabe4406001245ab921228b1298cc75c5935383694316a3a8469
7
- data.tar.gz: dcaf4142fb7e906c8cdb466c14a421bc8cd570c38bf240b7b93591dfc554deb025d135dedd45726252fa630133101c39da176987efdd9b09e8dd5d613094ecf7
6
+ metadata.gz: 51cd0b9b042fe549668137d6635a68589d031a72ab40fae39908604101fa632363b701546c194d87b0a3140714c10234434127fe4bd679f40c8d8d56855a26df
7
+ data.tar.gz: b7ccd7a213c9dbd9cd80db90b70421dd16e1b4a9d88a79b67b63ea210611ea72f66c805d07c698baf4dae78dd854292012e56b89e07db04f21e9aed627813cfc
@@ -8,8 +8,8 @@ module ImportJS
8
8
  'aliases' => {},
9
9
  'declaration_keyword' => 'var',
10
10
  'excludes' => [],
11
- 'jshint_cmd' => 'jshint',
12
11
  'lookup_paths' => ['.'],
12
+ 'strip_file_extensions' => ['.js', '.jsx']
13
13
  }
14
14
 
15
15
  # Class that initializes configuration from a .importjs.json file
@@ -28,19 +28,27 @@ module ImportJS
28
28
  @config[key]
29
29
  end
30
30
 
31
- def resolve_alias(variable_name)
31
+ # @param variable_name [String]
32
+ # @param path_to_current_file [String?]
33
+ # @return [ImportJS::JSModule?]
34
+ def resolve_alias(variable_name, path_to_current_file)
32
35
  path = @config['aliases'][variable_name]
33
36
  return resolve_destructured_alias(variable_name) unless path
34
37
 
35
38
  path = path['path'] if path.is_a? Hash
36
- ImportJS::JSModule.new(nil, path, self)
39
+
40
+ if path_to_current_file && !path_to_current_file.empty?
41
+ path = path.sub(/\{filename\}/,
42
+ File.basename(path_to_current_file, '.*'))
43
+ end
44
+ ImportJS::JSModule.new(nil, path, [])
37
45
  end
38
46
 
39
47
  def resolve_destructured_alias(variable_name)
40
48
  @config['aliases'].each do |_, path|
41
49
  next if path.is_a? String
42
50
  if (path['destructure'] || []).include?(variable_name)
43
- js_module = ImportJS::JSModule.new(nil, path['path'], self)
51
+ js_module = ImportJS::JSModule.new(nil, path['path'], [])
44
52
  js_module.is_destructured = true
45
53
  return js_module
46
54
  end
@@ -0,0 +1,154 @@
1
+ # encoding: utf-8
2
+ module ImportJS
3
+ end
4
+
5
+ class ImportJS::EmacsEditor
6
+ attr_accessor :current_word
7
+
8
+ def initialize
9
+ loop do
10
+ input = gets.chomp
11
+ command, value, path = input.split(':')
12
+
13
+ begin
14
+ @path = path
15
+ @file = File.readlines(path).map(&:chomp)
16
+ @current_word = value
17
+
18
+ case command
19
+ when 'import'
20
+ ImportJS::Importer.new(self).import
21
+ write_file
22
+ puts 'import:success'
23
+ when 'goto'
24
+ ImportJS::Importer.new(self).goto
25
+ end
26
+ rescue Exception => e
27
+ puts e.inspect
28
+ end
29
+ end
30
+ end
31
+
32
+ def write_file
33
+ new_file = File.open(@path, 'w')
34
+ @file.each {|line| new_file.puts(line) }
35
+ new_file.close
36
+ end
37
+
38
+ # Open a file specified by a path.
39
+ #
40
+ # @param file_path [String]
41
+ def open_file(file_path)
42
+ puts "goto:success:#{File.expand_path(file_path)}"
43
+ end
44
+
45
+ # Get the path to the file currently being edited. May return `nil` if an
46
+ # anonymous file is being edited.
47
+ #
48
+ # @return [String?]
49
+ def path_to_current_file
50
+ # Not yet implemented for Emacs
51
+ nil
52
+ end
53
+
54
+ # Display a message to the user.
55
+ #
56
+ # @param str [String]
57
+ def message(str)
58
+ puts str
59
+ end
60
+
61
+ # Read the entire file into a string.
62
+ #
63
+ # @return [String]
64
+ def current_file_content
65
+ @file.join('\n')
66
+ end
67
+
68
+ # Reads a line from the file.
69
+ #
70
+ # Lines are one-indexed, so 1 means the first line in the file.
71
+ # @return [String]
72
+ def read_line(line_number)
73
+ @file[line_number - 1]
74
+ end
75
+
76
+ # Get the cursor position.
77
+ #
78
+ # @return [Array(Number, Number)]
79
+ def cursor
80
+ return 0, 0
81
+ end
82
+
83
+ # Place the cursor at a specified position.
84
+ #
85
+ # @param position_tuple [Array(Number, Number)] the row and column to place
86
+ # the cursor at.
87
+ def cursor=(position_tuple)
88
+ end
89
+
90
+ # Delete a line.
91
+ #
92
+ # @param line_number [Number] One-indexed line number.
93
+ # 1 is the first line in the file.
94
+ def delete_line(line_number)
95
+ @file.delete_at(line_number - 1)
96
+ end
97
+
98
+ # Append a line right after the specified line.
99
+ #
100
+ # Lines are one-indexed, but you need to support appending to line 0 (add
101
+ # content at top of file).
102
+ # @param line_number [Number]
103
+ def append_line(line_number, str)
104
+ @file.insert(line_number, str)
105
+ end
106
+
107
+ # Count the number of lines in the file.
108
+ #
109
+ # @return [Number] the number of lines in the file
110
+ def count_lines
111
+ @file.size
112
+ end
113
+
114
+ # Ask the user to select something from a list of alternatives.
115
+ #
116
+ # @param heading [String] A heading text
117
+ # @param alternatives [Array<String>] A list of alternatives
118
+ # @return [Number, nil] the index of the selected alternative, or nil if
119
+ # nothing was selected.
120
+ def ask_for_selection(heading, alternatives)
121
+ puts "asking for selection"
122
+ puts heading
123
+ puts JSON.pretty_generate(alternatives)
124
+ return
125
+
126
+ # need to implement this
127
+ escaped_list = [heading]
128
+ escaped_list << alternatives.each_with_index.map do |alternative, i|
129
+ "\"#{i + 1}: #{alternative}\""
130
+ end
131
+ escaped_list_string = '[' + escaped_list.join(',') + ']'
132
+
133
+ selected_index = VIM.evaluate("inputlist(#{escaped_list_string})")
134
+ return if selected_index < 1
135
+ selected_index - 1
136
+ end
137
+
138
+ # Get the preferred max length of a line
139
+ # @return [Number?]
140
+ def max_line_length
141
+ 80
142
+ end
143
+
144
+ # @return [String] shiftwidth number of spaces if expandtab is not set,
145
+ # otherwise `\t`
146
+ def tab
147
+ return ' ' * shift_width || 2
148
+ end
149
+
150
+ # @return [Number?]
151
+ def shift_width
152
+ 2
153
+ end
154
+ end
@@ -0,0 +1,111 @@
1
+ module ImportJS
2
+ # Class that represents an import statement, e.g.
3
+ # "const foo = require('foo');"
4
+ class ImportStatement
5
+ REGEX_CONST_LET_VAR = %r{
6
+ \A
7
+ (?:const|let|var)\s+ # declaration keyword
8
+ (?<assignment>.+?) # <assignment> variable assignment
9
+ \s*=\s*
10
+ require\(
11
+ (?<quote>'|") # <quote> opening quote
12
+ (?<path>[^\2]+) # <path> module path
13
+ \k<quote> # closing quote
14
+ \);?
15
+ \s*
16
+ }xm
17
+
18
+ REGEX_IMPORT = %r{
19
+ \A
20
+ import\s+
21
+ (?<assignment>.*?) # <assignment> variable assignment
22
+ \s+from\s+
23
+ (?<quote>'|") # <quote> opening quote
24
+ (?<path>[^\2]+) # <path> module path
25
+ \k<quote> # closing quote
26
+ ;?\s*
27
+ }xm
28
+
29
+ attr_accessor :assignment
30
+ attr_accessor :original_import_string # a cache of the parsed import string
31
+ attr_accessor :variables
32
+ attr_accessor :is_destructured # can't use `destructured?` because of 1.9.3
33
+ attr_accessor :path
34
+
35
+ # @param string [String] a possible import statement, e.g.
36
+ # `const foo = require('foo');`
37
+ # @return [ImportJS::ImportStatement?] a parsed statement, or nil if the
38
+ # string can't be parsed
39
+ def self.parse(string)
40
+ match = REGEX_CONST_LET_VAR.match(string) ||
41
+ REGEX_IMPORT.match(string)
42
+ return unless match
43
+
44
+ statement = new
45
+ statement.original_import_string = match.string
46
+ statement.path = match[:path]
47
+ statement.assignment = match[:assignment]
48
+ if dest_match = statement.assignment.match(/\{\s*(.*)\s*\}/)
49
+ statement.variables = dest_match[1].split(/,\s*/).map(&:strip)
50
+ statement.is_destructured = true
51
+ else
52
+ statement.variables = [statement.assignment]
53
+ end
54
+ statement
55
+ end
56
+
57
+ # Injects a new variable into an already existing set of destructured
58
+ # variables.
59
+ # @param variable_name [String]
60
+ def inject_variable(variable_name)
61
+ variables << variable_name
62
+ variables.sort!.uniq!
63
+
64
+ @original_import_string = nil # clear import string cache if there was one
65
+ end
66
+
67
+ # Deletes a variable from an already existing set of destructured
68
+ # variables.
69
+ # @param variable_name [String]
70
+ def delete_variable(variable_name)
71
+ variables.delete(variable_name)
72
+
73
+ @original_import_string = nil # clear import string cache if there was one
74
+ end
75
+
76
+ # @return [Array] an array that can be used in `uniq!` to dedupe equal
77
+ # statements, e.g.
78
+ # `const foo = require('foo');`
79
+ # `import foo from 'foo';`
80
+ def normalize
81
+ [variables, path]
82
+ end
83
+
84
+ # @param declaration_keyword [String] const, let, var, or import
85
+ # @param max_line_length [Number] where to cap lines at
86
+ # @param tab [String] e.g. ' ' (two spaces)
87
+ # @return a generated import statement string
88
+ def to_import_string(declaration_keyword, max_line_length, tab)
89
+ return original_import_string if original_import_string
90
+
91
+ declaration = if is_destructured
92
+ "#{declaration_keyword} { #{variables.join(', ')} }"
93
+ else
94
+ "#{declaration_keyword} #{variables.first}"
95
+ end
96
+
97
+ equals, value = if declaration_keyword == 'import'
98
+ ['from', "'#{path}';"]
99
+ else
100
+ ['=', "require('#{path}');"]
101
+ end
102
+
103
+ if max_line_length &&
104
+ "#{declaration} #{equals} #{value}".length > max_line_length
105
+ "#{declaration} #{equals}\n#{tab}#{value}"
106
+ else
107
+ "#{declaration} #{equals} #{value}"
108
+ end
109
+ end
110
+ end
111
+ end
@@ -23,8 +23,16 @@ module ImportJS
23
23
  current_row, current_col = @editor.cursor
24
24
 
25
25
  old_buffer_lines = @editor.count_lines
26
- import_one_variable variable_name
27
- return unless lines_changed = @editor.count_lines - old_buffer_lines
26
+ js_module = find_one_js_module(variable_name)
27
+ return unless js_module
28
+
29
+ old_imports = find_current_imports
30
+ inject_js_module(variable_name, js_module, old_imports[:imports])
31
+ replace_imports(old_imports[:newline_count],
32
+ old_imports[:imports],
33
+ old_imports[:imports_start_at])
34
+ lines_changed = @editor.count_lines - old_buffer_lines
35
+ return unless lines_changed
28
36
  @editor.cursor = [current_row + lines_changed, current_col]
29
37
  end
30
38
 
@@ -39,103 +47,148 @@ module ImportJS
39
47
  @editor.open_file(js_module.file_path)
40
48
  end
41
49
 
50
+ def fix_imports
51
+ remove_unused_imports
52
+ import_all
53
+ end
54
+
42
55
  # Finds all variables that haven't yet been imported.
43
56
  def import_all
44
57
  @config.refresh
45
- unused_variables = find_unused_variables
58
+ undefined_variables = run_eslint_command.map do |line|
59
+ /"([^"]+)" is not defined/.match(line) do |match_data|
60
+ match_data[1]
61
+ end
62
+ end.compact.uniq
46
63
 
47
- if unused_variables.empty?
48
- message('No variables to import')
49
- return
64
+ return message('No variables to import') if undefined_variables.empty?
65
+
66
+ old_imports = find_current_imports
67
+ undefined_variables.each do |variable|
68
+ if js_module = find_one_js_module(variable)
69
+ inject_js_module(variable, js_module, old_imports[:imports])
70
+ end
50
71
  end
72
+ replace_imports(old_imports[:newline_count],
73
+ old_imports[:imports],
74
+ old_imports[:imports_start_at])
75
+ end
76
+
77
+ def remove_unused_imports
78
+ @config.refresh
79
+ unused_variables = run_eslint_command.map do |line|
80
+ /"([^"]+)" is defined but never used/.match(line) do |match_data|
81
+ match_data[1]
82
+ end
83
+ end.compact.uniq
51
84
 
52
- unused_variables.each do |variable|
53
- import_one_variable(variable)
85
+ old_imports = find_current_imports
86
+ new_imports = old_imports[:imports].reject do |import_statement|
87
+ unused_variables.each do |unused_variable|
88
+ import_statement.delete_variable(unused_variable)
89
+ end
90
+ import_statement.variables.empty?
54
91
  end
92
+ replace_imports(old_imports[:newline_count],
93
+ new_imports,
94
+ old_imports[:imports_start_at])
55
95
  end
56
96
 
57
97
  private
58
98
 
59
99
  def message(str)
60
- @editor.message("[import-js] #{str}")
100
+ @editor.message("ImportJS: #{str}")
61
101
  end
62
102
 
63
- # @return [Array]
64
- def find_unused_variables
65
- content = "/* jshint undef: true, strict: true */\n" +
66
- "/* eslint no-unused-vars: [2, { \"vars\": \"all\", \"args\": \"none\" }] */\n" +
67
- @editor.current_file_content
68
-
69
- out, _ = Open3.capture3("#{@config.get('jshint_cmd')} -", stdin_data: content)
70
- result = []
71
- out.split("\n").each do |line|
72
- /.*['"]([^'"]+)['"] is not defined/.match(line) do |match_data|
73
- result << match_data[1]
74
- end
103
+ # @return [Array<String>] the output from eslint, line by line
104
+ def run_eslint_command
105
+ command = %w[
106
+ eslint
107
+ --stdin
108
+ --format compact
109
+ --rule 'no-undef: 2'
110
+ --rule 'no-unused-vars: [2, { "vars": "all", "args": "none" }]'
111
+ ].join(' ')
112
+ out, err = Open3.capture3(command,
113
+ stdin_data: @editor.current_file_content)
114
+
115
+ if out =~ /Error - Parsing error: / ||
116
+ out =~ /Unrecoverable syntax error/
117
+ fail ImportJS::ParseError.new, out
118
+ end
119
+
120
+ if err =~ /SyntaxError: / ||
121
+ err =~ /eslint: command not found/
122
+ fail ImportJS::ParseError.new, err
75
123
  end
76
- result.uniq
124
+
125
+ out.split("\n")
77
126
  end
78
127
 
79
128
  # @param variable_name [String]
80
- def import_one_variable(variable_name)
129
+ # @return [ImportJS::JSModule?]
130
+ def find_one_js_module(variable_name)
81
131
  @timing = { start: Time.now }
82
132
  js_modules = find_js_modules(variable_name)
83
133
  @timing[:end] = Time.now
84
134
  if js_modules.empty?
85
- message(<<-EOS.split.join(' '))
86
- No js module to import for variable `#{variable_name}` #{timing}
87
- EOS
135
+ message(
136
+ "No JS module to import for variable `#{variable_name}` #{timing}")
88
137
  return
89
138
  end
90
139
 
91
- resolved_js_module = resolve_one_js_module(js_modules, variable_name)
92
- return unless resolved_js_module
93
-
94
- write_imports(variable_name, resolved_js_module)
140
+ resolve_one_js_module(js_modules, variable_name)
95
141
  end
96
142
 
97
143
  # @param variable_name [String]
98
144
  # @param js_module [ImportJS::JSModule]
99
- def write_imports(variable_name, js_module)
100
- old_imports = find_current_imports
101
-
102
- # Ensure that there is a blank line after the block of all imports
103
- unless @editor.read_line(old_imports[:newline_count] + 1).strip.empty?
104
- @editor.append_line(old_imports[:newline_count], '')
105
- end
106
-
107
- modified_imports = old_imports[:imports] # Array
108
-
145
+ # @param imports [Array<ImportJS::ImportStatement>]
146
+ def inject_js_module(variable_name, js_module, imports)
109
147
  # Add new import to the block of imports, wrapping at the max line length
110
148
  unless js_module.is_destructured && inject_destructured_variable(
111
- variable_name, js_module, modified_imports)
112
- modified_imports << generate_import(variable_name, js_module)
149
+ variable_name, js_module, imports)
150
+ imports.unshift(js_module.to_import_statement(variable_name))
113
151
  end
114
152
 
115
- # Sort the block of imports
116
- modified_imports.sort!.uniq! do |import|
117
- # Determine uniqueness by discarding the declaration keyword (`const`,
118
- # `let`, or `var`) and normalizing multiple whitespace chars to single
119
- # spaces.
120
- import.sub(/\A(const|let|var)\s+/, '').sub(/\s\s+/s, ' ')
153
+ # Remove duplicate import statements
154
+ imports.uniq!(&:normalize)
155
+ end
156
+
157
+ # @param old_imports_lines [Number]
158
+ # @param new_imports [Array<ImportJS::ImportStatement>]
159
+ # @param imports_start_at [Number]
160
+ def replace_imports(old_imports_lines, new_imports, imports_start_at)
161
+ # Ensure that there is a blank line after the block of all imports
162
+ if old_imports_lines + new_imports.length > 0 &&
163
+ !@editor.read_line(old_imports_lines + imports_start_at + 1).strip.empty?
164
+ @editor.append_line(old_imports_lines + imports_start_at, '')
121
165
  end
122
166
 
167
+ # Generate import strings
168
+ import_strings = new_imports.map do |import|
169
+ import.to_import_string(
170
+ @config.get('declaration_keyword'),
171
+ @editor.max_line_length,
172
+ @editor.tab)
173
+ end.sort
174
+
123
175
  # Delete old imports, then add the modified list back in.
124
- old_imports[:newline_count].times { @editor.delete_line(1) }
125
- modified_imports.reverse_each do |import|
176
+ old_imports_lines.times { @editor.delete_line(1 + imports_start_at) }
177
+ import_strings.reverse_each do |import_string|
126
178
  # We need to add each line individually because the Vim buffer will
127
179
  # convert newline characters to `~@`.
128
- import.split("\n").reverse_each { |line| @editor.append_line(0, line) }
180
+ import_string.split("\n").reverse_each do |line|
181
+ @editor.append_line(0 + imports_start_at, line)
182
+ end
129
183
  end
130
184
  end
131
185
 
132
186
  def inject_destructured_variable(variable_name, js_module, imports)
133
187
  imports.each do |import|
134
- match = import.match(%r{((const|let|var) \{ )(.*)( \} = require\('#{js_module.import_path}'\);)})
135
- next unless match
188
+ next unless import.path == js_module.import_path
189
+ next unless import.is_destructured
136
190
 
137
- variables = match[3].split(/,\s*/).concat([variable_name]).uniq.sort
138
- import.sub!(/.*/, "#{match[1]}#{variables.join(', ')}#{match[4]}")
191
+ import.inject_variable(variable_name)
139
192
  return true
140
193
  end
141
194
  false
@@ -150,52 +203,38 @@ module ImportJS
150
203
  potential_import_lines << line
151
204
  end
152
205
 
206
+ result = {
207
+ imports: [],
208
+ newline_count: 0,
209
+ imports_start_at: 0
210
+ }
211
+
212
+ if potential_import_lines[0] =~ /(['"])use strict\1;?/
213
+ result[:imports_start_at] = 1
214
+ potential_import_lines.shift
215
+ end
216
+
153
217
  # We need to put the potential imports back into a blob in order to scan
154
218
  # for multiline imports
155
219
  potential_imports_blob = potential_import_lines.join("\n")
156
220
 
157
- imports = []
158
-
159
221
  # Scan potential imports for everything ending in a semicolon, then
160
222
  # iterate through those and stop at anything that's not an import.
161
223
  potential_imports_blob.scan(/^.*?;/m).each do |potential_import|
162
- break unless potential_import.match(
163
- /(?:const|let|var)\s+.+=\s+require\(.*\).*;/)
164
- imports << potential_import
165
- end
166
-
167
- newline_count = imports.length + imports.reduce(0) do |sum, import|
168
- sum + import.scan(/\n/).length
169
- end
170
- {
171
- imports: imports,
172
- newline_count: newline_count
173
- }
174
- end
175
-
176
- # @param variable_name [String]
177
- # @param js_module [ImportJS::JSModule]
178
- # @return [String] the import string to be added to the imports block
179
- def generate_import(variable_name, js_module)
180
- declaration_keyword = @config.get('declaration_keyword')
181
- if js_module.is_destructured
182
- declaration = "#{declaration_keyword} { #{variable_name} } ="
183
- else
184
- declaration = "#{declaration_keyword} #{variable_name} ="
185
- end
186
- value = "require('#{js_module.import_path}');"
224
+ import_statement = ImportJS::ImportStatement.parse(potential_import)
225
+ break unless import_statement
187
226
 
188
- if @editor.max_line_length && "#{declaration} #{value}".length > @editor.max_line_length
189
- "#{declaration}\n#{@editor.tab}#{value}"
190
- else
191
- "#{declaration} #{value}"
227
+ result[:imports] << import_statement
228
+ result[:newline_count] += potential_import.scan(/\n/).length + 1
192
229
  end
230
+ result
193
231
  end
194
232
 
195
233
  # @param variable_name [String]
196
234
  # @return [Array]
197
235
  def find_js_modules(variable_name)
198
- if alias_module = @config.resolve_alias(variable_name)
236
+ if alias_module = @config.resolve_alias(variable_name,
237
+ @editor.path_to_current_file)
199
238
  return [alias_module]
200
239
  end
201
240
 
@@ -210,7 +249,8 @@ module ImportJS
210
249
  next if @config.get('excludes').any? do |glob_pattern|
211
250
  File.fnmatch(glob_pattern, f)
212
251
  end
213
- js_module = ImportJS::JSModule.new(lookup_path, f, @config)
252
+ js_module = ImportJS::JSModule.new(
253
+ lookup_path, f, @config.get('strip_file_extensions'))
214
254
  next if js_module.skip
215
255
  js_module
216
256
  end.compact
@@ -221,7 +261,7 @@ module ImportJS
221
261
  @config.package_dependencies.each do |dep|
222
262
  next unless dep =~ /^#{formatted_to_regex(variable_name)}$/
223
263
  js_module = ImportJS::JSModule.new(
224
- 'node_modules', "node_modules/#{dep}/package.json", @config)
264
+ 'node_modules', "node_modules/#{dep}/package.json", [])
225
265
  next if js_module.skip
226
266
  matched_modules << js_module
227
267
  end
@@ -248,8 +288,8 @@ module ImportJS
248
288
  end
249
289
 
250
290
  selected_index = @editor.ask_for_selection(
251
- "\"[import-js] Pick js module to import for '#{variable_name}': #{timing}\"",
252
- js_modules.map {|m| m.display_name}
291
+ "\"ImportJS: Pick JS module to import for '#{variable_name}': #{timing}\"",
292
+ js_modules.map(&:display_name)
253
293
  )
254
294
  return unless selected_index
255
295
  js_modules[selected_index]
@@ -11,8 +11,9 @@ module ImportJS
11
11
  # @param lookup_path [String] the lookup path in which this module was found
12
12
  # @param relative_file_path [String] a full path to the file, relative to
13
13
  # the project root.
14
- # @param configuration [ImportJS::Configuration]
15
- def initialize(lookup_path, relative_file_path, configuration)
14
+ # @param strip_file_extensions [Array] a list of file extensions to strip,
15
+ # e.g. ['.js', '.jsx']
16
+ def initialize(lookup_path, relative_file_path, strip_file_extensions)
16
17
  @lookup_path = lookup_path
17
18
  @file_path = relative_file_path
18
19
  if relative_file_path.end_with? '/package.json'
@@ -26,8 +27,11 @@ module ImportJS
26
27
  @import_path = match[1]
27
28
  else
28
29
  @import_path = relative_file_path
29
- unless configuration.get('keep_file_extensions')
30
- @import_path = @import_path.sub(/\.js.*$/, '')
30
+ strip_file_extensions.each do |ext|
31
+ if @import_path.end_with?(ext)
32
+ @import_path = @import_path[0...-ext.length]
33
+ break
34
+ end
31
35
  end
32
36
  end
33
37
 
@@ -42,5 +46,15 @@ module ImportJS
42
46
  parts << " (main: #{@main_file})" if @main_file
43
47
  parts.join('')
44
48
  end
49
+
50
+ # @param variable_name [String]
51
+ # @return [ImportJS::ImportStatement]
52
+ def to_import_statement(variable_name)
53
+ ImportJS::ImportStatement.new.tap do |statement|
54
+ statement.is_destructured = is_destructured
55
+ statement.variables = [variable_name]
56
+ statement.path = import_path
57
+ end
58
+ end
45
59
  end
46
60
  end
@@ -10,6 +10,14 @@ module ImportJS
10
10
  VIM.evaluate("expand('<cword>')")
11
11
  end
12
12
 
13
+ # Get the path to the file currently being edited. May return `nil` if an
14
+ # anonymous file is being edited.
15
+ #
16
+ # @return [String?]
17
+ def path_to_current_file
18
+ VIM.evaluate("expand('%')")
19
+ end
20
+
13
21
  # Open a file specified by a path.
14
22
  #
15
23
  # @param file_path [String]
data/lib/import_js.rb CHANGED
@@ -1,11 +1,17 @@
1
1
  # Namespace declaration
2
2
  module ImportJS
3
- # We initialize an empty "ImportJS" namespace here so that we can define
4
- # classes under that namespace, e.g. `ImportJS::Importer`.
3
+ # We initialize the "ImportJS" namespace here so that we can define classes
4
+ # under that namespace, e.g. `ImportJS::Importer`.
5
+
6
+ class ParseError < StandardError
7
+ # Error thrown when a JS file can't be parsed
8
+ end
5
9
  end
6
10
 
7
11
  require_relative 'import_js/js_module'
12
+ require_relative 'import_js/import_statement'
8
13
  require_relative 'import_js/importer'
9
14
  require_relative 'import_js/vim_editor'
15
+ require_relative 'import_js/emacs_editor'
10
16
  require_relative 'import_js/command_line_editor'
11
17
  require_relative 'import_js/configuration'
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.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henric Trotzig
@@ -21,6 +21,8 @@ files:
21
21
  - lib/import_js.rb
22
22
  - lib/import_js/command_line_editor.rb
23
23
  - lib/import_js/configuration.rb
24
+ - lib/import_js/emacs_editor.rb
25
+ - lib/import_js/import_statement.rb
24
26
  - lib/import_js/importer.rb
25
27
  - lib/import_js/js_module.rb
26
28
  - lib/import_js/vim_editor.rb