import_js 0.4.1 → 0.5.0
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 +4 -4
- data/bin/import-js +39 -9
- data/lib/import_js.rb +4 -3
- data/lib/import_js/command_line_editor.rb +2 -14
- data/lib/import_js/configuration.rb +5 -3
- data/lib/import_js/emacs_editor.rb +0 -17
- data/lib/import_js/import_statement.rb +93 -66
- data/lib/import_js/import_statements.rb +175 -0
- data/lib/import_js/importer.rb +122 -156
- data/lib/import_js/js_module.rb +24 -19
- data/lib/import_js/version.rb +1 -1
- data/lib/import_js/vim_editor.rb +0 -29
- data/lib/vim_import_js.rb +4 -0
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eddd4e67b47ab663fb4bb1fc39a2e11810f9f640
|
4
|
+
data.tar.gz: 399fee47fa49f677e9646ae1451a897869a441cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3269f091d4da05e069fd26f935450964495da18d1a970a77cacc6bea9fc5593c002c16c3cb53a2b8234ed2be711018aefbfb03e58e5b76e04cfd4b383ee9513
|
7
|
+
data.tar.gz: 545f69bfb8caadcc9bd30e3ae04ab73640d369272b47997be3e5c8718fee06f4f7f740fa9e608fa55872c4f606d04a8af9c9ff804867485ed7451a85714e4b8f
|
data/bin/import-js
CHANGED
@@ -5,22 +5,45 @@ require 'slop'
|
|
5
5
|
require 'json'
|
6
6
|
|
7
7
|
opts = Slop.parse do |o|
|
8
|
-
o.
|
9
|
-
o.
|
10
|
-
o.
|
11
|
-
o.
|
12
|
-
|
13
|
-
|
8
|
+
o.banner = 'Usage: import-js [<path-to-file>] [options] ...'
|
9
|
+
o.string '-w', '--word', 'A word/variable to import'
|
10
|
+
o.bool '--goto', 'Instead of importing, just print the path to a module'
|
11
|
+
o.array '--selections', 'A list of resolved selections, e.g. Foo:0,Bar:1'
|
12
|
+
o.string '--stdin-file-path',
|
13
|
+
'A path to the file whose content is being passed in as stdin. ' \
|
14
|
+
'This is used as a way to make sure that the right configuration ' \
|
15
|
+
'is applied.'
|
16
|
+
o.bool '--overwrite',
|
17
|
+
'Overwrite the file with the result after importing (the default ' \
|
18
|
+
'behavior is to print to stdout). This only applies if you are ' \
|
19
|
+
'passing in a file (<path-to-file>) as the first positional argument.'
|
20
|
+
o.string '--filename', '(deprecated) Alias for --stdin-file-path'
|
21
|
+
o.bool '--rewrite',
|
22
|
+
'Rewrite all current imports to match Import-JS configuration. ' \
|
23
|
+
'This does not add missing imports or remove unused imports.'
|
24
|
+
|
25
|
+
o.on '-v', '--version', 'Prints the current version' do
|
14
26
|
puts ImportJS::VERSION
|
15
27
|
exit
|
16
28
|
end
|
17
|
-
o.on '-h', '--help', '
|
29
|
+
o.on '-h', '--help', 'Prints help' do
|
18
30
|
puts o
|
19
31
|
exit
|
20
32
|
end
|
21
33
|
end
|
22
34
|
|
23
|
-
|
35
|
+
path_to_file = opts.arguments[0] || opts['stdin-file-path'] || opts[:filename]
|
36
|
+
|
37
|
+
file_contents = if STDIN.tty?
|
38
|
+
unless path_to_file
|
39
|
+
puts 'Error: missing <path-to-file>'
|
40
|
+
puts opts
|
41
|
+
exit 1
|
42
|
+
end
|
43
|
+
File.read(path_to_file).split("\n")
|
44
|
+
else
|
45
|
+
STDIN.read.split("\n")
|
46
|
+
end
|
24
47
|
|
25
48
|
if opts[:selections]
|
26
49
|
# Convert array of string tuples to hash, `word` => `selectedIndex`
|
@@ -30,12 +53,15 @@ if opts[:selections]
|
|
30
53
|
end]
|
31
54
|
end
|
32
55
|
|
33
|
-
editor = ImportJS::CommandLineEditor.new(
|
56
|
+
editor = ImportJS::CommandLineEditor.new(
|
57
|
+
file_contents, opts.to_hash.merge(path_to_file: path_to_file))
|
34
58
|
importer = ImportJS::Importer.new(editor)
|
35
59
|
if opts.goto?
|
36
60
|
importer.goto
|
37
61
|
elsif opts[:word]
|
38
62
|
importer.import
|
63
|
+
elsif opts[:rewrite]
|
64
|
+
importer.rewrite_imports
|
39
65
|
else
|
40
66
|
importer.fix_imports
|
41
67
|
end
|
@@ -43,6 +69,10 @@ end
|
|
43
69
|
if opts.goto?
|
44
70
|
# Print the path to the module to go to
|
45
71
|
puts editor.goto
|
72
|
+
elsif opts[:overwrite]
|
73
|
+
File.open(path_to_file, 'w') do |f|
|
74
|
+
f.write editor.current_file_content + "\n"
|
75
|
+
end
|
46
76
|
else
|
47
77
|
# Print resulting file to stdout
|
48
78
|
puts editor.current_file_content
|
data/lib/import_js.rb
CHANGED
@@ -4,15 +4,15 @@ module ImportJS
|
|
4
4
|
# under that namespace, e.g. `ImportJS::Importer`.
|
5
5
|
|
6
6
|
class ParseError < StandardError
|
7
|
-
# Error
|
7
|
+
# Error raised when a JS file can't be parsed
|
8
8
|
end
|
9
9
|
|
10
10
|
class FindError < StandardError
|
11
|
-
# Error
|
11
|
+
# Error raised when the find command fails
|
12
12
|
end
|
13
13
|
|
14
14
|
class ClientTooOldError < StandardError
|
15
|
-
# Error
|
15
|
+
# Error raised when the client is too old to handle the config
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -20,6 +20,7 @@ require_relative 'import_js/command_line_editor'
|
|
20
20
|
require_relative 'import_js/configuration'
|
21
21
|
require_relative 'import_js/emacs_editor'
|
22
22
|
require_relative 'import_js/import_statement'
|
23
|
+
require_relative 'import_js/import_statements'
|
23
24
|
require_relative 'import_js/importer'
|
24
25
|
require_relative 'import_js/js_module'
|
25
26
|
require_relative 'import_js/version'
|
@@ -7,7 +7,7 @@ module ImportJS
|
|
7
7
|
@ask_for_selections = []
|
8
8
|
@selections = opts[:selections] unless opts[:selections].empty?
|
9
9
|
@word = opts[:word]
|
10
|
-
@
|
10
|
+
@path_to_file = opts[:path_to_file]
|
11
11
|
end
|
12
12
|
|
13
13
|
# @return [String]
|
@@ -17,7 +17,7 @@ module ImportJS
|
|
17
17
|
|
18
18
|
# @return [String?]
|
19
19
|
def path_to_current_file
|
20
|
-
@
|
20
|
+
@path_to_file
|
21
21
|
end
|
22
22
|
|
23
23
|
# @param file_path [String]
|
@@ -110,17 +110,5 @@ module ImportJS
|
|
110
110
|
nil
|
111
111
|
end
|
112
112
|
end
|
113
|
-
|
114
|
-
# Get the preferred max length of a line.
|
115
|
-
# @return [Number?]
|
116
|
-
def max_line_length
|
117
|
-
80
|
118
|
-
end
|
119
|
-
|
120
|
-
# @return [String] shiftwidth number of spaces if expandtab is not set,
|
121
|
-
# otherwise `\t`.
|
122
|
-
def tab
|
123
|
-
' '
|
124
|
-
end
|
125
113
|
end
|
126
114
|
end
|
@@ -15,9 +15,11 @@ module ImportJS
|
|
15
15
|
'import_dev_dependencies' => false,
|
16
16
|
'import_function' => 'require',
|
17
17
|
'lookup_paths' => ['.'],
|
18
|
+
'max_line_length' => 80,
|
18
19
|
'minimum_version' => '0.0.0',
|
19
20
|
'strip_file_extensions' => ['.js', '.jsx'],
|
20
21
|
'strip_from_path' => nil,
|
22
|
+
'tab' => ' ',
|
21
23
|
'use_relative_paths' => false,
|
22
24
|
}.freeze
|
23
25
|
|
@@ -110,9 +112,9 @@ module ImportJS
|
|
110
112
|
return if Gem::Dependency.new('', ">= #{minimum_version}")
|
111
113
|
.match?('', VERSION)
|
112
114
|
|
113
|
-
|
114
|
-
|
115
|
-
|
115
|
+
raise ClientTooOldError,
|
116
|
+
'The .importjs.json file you are using requires version ' \
|
117
|
+
"#{get('minimum_version')}. You are using #{VERSION}."
|
116
118
|
end
|
117
119
|
end
|
118
120
|
end
|
@@ -138,22 +138,5 @@ module ImportJS
|
|
138
138
|
return if selected_index < 1
|
139
139
|
selected_index - 1
|
140
140
|
end
|
141
|
-
|
142
|
-
# Get the preferred max length of a line
|
143
|
-
# @return [Number?]
|
144
|
-
def max_line_length
|
145
|
-
80
|
146
|
-
end
|
147
|
-
|
148
|
-
# @return [String] shiftwidth number of spaces if expandtab is not set,
|
149
|
-
# otherwise `\t`
|
150
|
-
def tab
|
151
|
-
' ' * shift_width || 2
|
152
|
-
end
|
153
|
-
|
154
|
-
# @return [Number?]
|
155
|
-
def shift_width
|
156
|
-
2
|
157
|
-
end
|
158
141
|
end
|
159
142
|
end
|
@@ -9,12 +9,13 @@ module ImportJS
|
|
9
9
|
(?<declaration_keyword>const|let|var)\s+ # <declaration_keyword>
|
10
10
|
(?<assignment>.+?) # <assignment> variable assignment
|
11
11
|
\s*=\s*
|
12
|
-
(?<import_function
|
12
|
+
(?<import_function>\w+?)\( # <import_function> variable assignment
|
13
13
|
(?<quote>'|") # <quote> opening quote
|
14
|
-
(?<path>[^\2]+)
|
14
|
+
(?<path>[^\2\n]+) # <path> module path
|
15
15
|
\k<quote> # closing quote
|
16
16
|
\);?
|
17
17
|
\s*
|
18
|
+
\Z
|
18
19
|
/xm
|
19
20
|
|
20
21
|
REGEX_IMPORT = /
|
@@ -23,12 +24,14 @@ module ImportJS
|
|
23
24
|
(?<assignment>.*?) # <assignment> variable assignment
|
24
25
|
\s+from\s+
|
25
26
|
(?<quote>'|") # <quote> opening quote
|
26
|
-
(?<path>[^\2]+)
|
27
|
+
(?<path>[^\2\n]+) # <path> module path
|
27
28
|
\k<quote> # closing quote
|
28
29
|
;?\s*
|
30
|
+
\Z
|
29
31
|
/xm
|
30
32
|
|
31
33
|
REGEX_NAMED = /
|
34
|
+
\A
|
32
35
|
(?: # non-capturing group
|
33
36
|
(?<default>.*?) # <default> default import
|
34
37
|
,\s*
|
@@ -38,6 +41,7 @@ module ImportJS
|
|
38
41
|
(?<named>.*) # <named> named imports
|
39
42
|
\s*
|
40
43
|
\}
|
44
|
+
\Z
|
41
45
|
/xm
|
42
46
|
|
43
47
|
attr_accessor :assignment
|
@@ -59,50 +63,67 @@ module ImportJS
|
|
59
63
|
REGEX_IMPORT.match(string)
|
60
64
|
return unless match
|
61
65
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
70
|
-
dest_match = statement.assignment.match(REGEX_NAMED)
|
66
|
+
import_function = if match.names.include?('import_function')
|
67
|
+
match[:import_function]
|
68
|
+
else
|
69
|
+
'require'
|
70
|
+
end
|
71
|
+
|
72
|
+
dest_match = match[:assignment].match(REGEX_NAMED)
|
71
73
|
if dest_match
|
72
|
-
|
73
|
-
|
74
|
-
dest_match[:named].split(/,\s*/).map(&:strip)
|
74
|
+
default_import = dest_match[:default]
|
75
|
+
named_imports = dest_match[:named].split(/,\s*/).map(&:strip)
|
75
76
|
else
|
76
|
-
|
77
|
+
default_import = match[:assignment]
|
78
|
+
return unless default_import =~ /\A\w+\Z/
|
77
79
|
end
|
78
|
-
statement
|
79
|
-
end
|
80
80
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
81
|
+
new(
|
82
|
+
assignment: match[:assignment],
|
83
|
+
declaration_keyword: match[:declaration_keyword],
|
84
|
+
default_import: default_import,
|
85
|
+
import_function: import_function,
|
86
|
+
named_imports: named_imports,
|
87
|
+
original_import_string: match.string,
|
88
|
+
path: match[:path]
|
89
|
+
)
|
86
90
|
end
|
87
91
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
named_imports
|
94
|
-
|
95
|
-
|
92
|
+
def initialize(
|
93
|
+
assignment: nil,
|
94
|
+
declaration_keyword: nil,
|
95
|
+
default_import: nil,
|
96
|
+
import_function: nil,
|
97
|
+
named_imports: nil,
|
98
|
+
original_import_string: nil,
|
99
|
+
path: nil
|
100
|
+
)
|
101
|
+
@assignment = assignment
|
102
|
+
@declaration_keyword = declaration_keyword
|
103
|
+
@default_import = default_import
|
104
|
+
@import_function = import_function
|
105
|
+
@named_imports = named_imports
|
106
|
+
@original_import_string = original_import_string
|
107
|
+
@path = path
|
96
108
|
end
|
97
109
|
|
98
110
|
# Deletes a variable from an already existing default import or set of
|
99
|
-
#
|
111
|
+
# named imports.
|
100
112
|
# @param variable_name [String]
|
101
|
-
def delete_variable(variable_name)
|
102
|
-
|
103
|
-
@named_imports.delete(variable_name) if named_imports?
|
113
|
+
def delete_variable!(variable_name)
|
114
|
+
touched = false
|
104
115
|
|
105
|
-
|
116
|
+
if default_import == variable_name
|
117
|
+
@default_import = nil
|
118
|
+
touched = true
|
119
|
+
end
|
120
|
+
|
121
|
+
if named_imports?
|
122
|
+
deleted = @named_imports.delete(variable_name)
|
123
|
+
touched = true if deleted
|
124
|
+
end
|
125
|
+
|
126
|
+
clear_import_string_cache if touched
|
106
127
|
end
|
107
128
|
|
108
129
|
# @return [Boolean] true if there are named imports
|
@@ -116,39 +137,38 @@ module ImportJS
|
|
116
137
|
default_import.nil? && !named_imports?
|
117
138
|
end
|
118
139
|
|
119
|
-
# @return [
|
120
|
-
#
|
121
|
-
|
122
|
-
|
140
|
+
# @return [Boolean] true if this instance was created through parsing an
|
141
|
+
# existing import and it hasn't been altered since it was created.
|
142
|
+
def parsed_and_untouched?
|
143
|
+
!original_import_string.nil?
|
144
|
+
end
|
145
|
+
|
146
|
+
# @return [Array] an array that can be used in `sort` and `uniq`
|
123
147
|
def to_normalized
|
124
|
-
[default_import, named_imports
|
148
|
+
[default_import || '', named_imports || '']
|
149
|
+
end
|
150
|
+
|
151
|
+
# @return [Array<String>] Array of all variables that this ImportStatement
|
152
|
+
# imports.
|
153
|
+
def variables
|
154
|
+
[@default_import, *@named_imports].compact
|
125
155
|
end
|
126
156
|
|
127
157
|
# @param max_line_length [Number] where to cap lines at
|
128
158
|
# @param tab [String] e.g. ' ' (two spaces)
|
129
|
-
# @return [Array] generated import statement strings
|
159
|
+
# @return [Array<String>] generated import statement strings
|
130
160
|
def to_import_strings(max_line_length, tab)
|
131
161
|
return [original_import_string] if original_import_string
|
132
162
|
|
133
163
|
if declaration_keyword == 'import'
|
134
164
|
# ES2015 Modules (ESM) syntax can support default imports and
|
135
165
|
# named imports on the same line.
|
136
|
-
if named_imports?
|
137
|
-
|
138
|
-
else
|
139
|
-
[default_import_string(max_line_length, tab)]
|
140
|
-
end
|
166
|
+
return [named_import_string(max_line_length, tab)] if named_imports?
|
167
|
+
[default_import_string(max_line_length, tab)]
|
141
168
|
else # const/var
|
142
169
|
strings = []
|
143
|
-
|
144
|
-
if
|
145
|
-
strings << default_import_string(max_line_length, tab)
|
146
|
-
end
|
147
|
-
|
148
|
-
if named_imports?
|
149
|
-
strings << named_import_string(max_line_length, tab)
|
150
|
-
end
|
151
|
-
|
170
|
+
strings << default_import_string(max_line_length, tab) if default_import
|
171
|
+
strings << named_import_string(max_line_length, tab) if named_imports?
|
152
172
|
strings
|
153
173
|
end
|
154
174
|
end
|
@@ -156,15 +176,22 @@ module ImportJS
|
|
156
176
|
# Merge another ImportStatement into this one.
|
157
177
|
# @param import_statement [ImportJS::ImportStatement]
|
158
178
|
def merge(import_statement)
|
159
|
-
if import_statement.default_import
|
179
|
+
if import_statement.default_import &&
|
180
|
+
@default_import != import_statement.default_import
|
160
181
|
@default_import = import_statement.default_import
|
161
182
|
clear_import_string_cache
|
162
183
|
end
|
163
184
|
|
164
185
|
if import_statement.named_imports?
|
165
186
|
@named_imports ||= []
|
187
|
+
original_named_imports = @named_imports.clone
|
166
188
|
@named_imports.concat(import_statement.named_imports)
|
167
189
|
@named_imports.sort!.uniq!
|
190
|
+
clear_import_string_cache if original_named_imports != @named_imports
|
191
|
+
end
|
192
|
+
|
193
|
+
if @declaration_keyword != import_statement.declaration_keyword
|
194
|
+
@declaration_keyword = import_statement.declaration_keyword
|
168
195
|
clear_import_string_cache
|
169
196
|
end
|
170
197
|
end
|
@@ -181,7 +208,7 @@ module ImportJS
|
|
181
208
|
# @return [Array]
|
182
209
|
def equals_and_value
|
183
210
|
return ['from', "'#{path}';"] if declaration_keyword == 'import'
|
184
|
-
['=', "#{import_function}('#{path}');"]
|
211
|
+
['=', "#{@import_function}('#{path}');"]
|
185
212
|
end
|
186
213
|
|
187
214
|
# @param max_line_length [Number] where to cap lines at
|
@@ -189,10 +216,10 @@ module ImportJS
|
|
189
216
|
# @return [String] import statement, wrapped at max line length if necessary
|
190
217
|
def default_import_string(max_line_length, tab)
|
191
218
|
equals, value = equals_and_value
|
192
|
-
line = "#{declaration_keyword} #{default_import} #{equals} #{value}"
|
219
|
+
line = "#{@declaration_keyword} #{@default_import} #{equals} #{value}"
|
193
220
|
return line unless line_too_long?(line, max_line_length)
|
194
221
|
|
195
|
-
"#{declaration_keyword} #{default_import} #{equals}\n#{tab}#{value}"
|
222
|
+
"#{@declaration_keyword} #{@default_import} #{equals}\n#{tab}#{value}"
|
196
223
|
end
|
197
224
|
|
198
225
|
# @param max_line_length [Number] where to cap lines at
|
@@ -200,17 +227,17 @@ module ImportJS
|
|
200
227
|
# @return [String] import statement, wrapped at max line length if necessary
|
201
228
|
def named_import_string(max_line_length, tab)
|
202
229
|
equals, value = equals_and_value
|
203
|
-
if declaration_keyword == 'import' && default_import
|
204
|
-
prefix = "#{default_import}, "
|
230
|
+
if @declaration_keyword == 'import' && @default_import
|
231
|
+
prefix = "#{@default_import}, "
|
205
232
|
end
|
206
233
|
|
207
|
-
named = "{ #{named_imports.join(', ')} }"
|
208
|
-
line = "#{declaration_keyword} #{prefix}#{named} #{equals} " \
|
234
|
+
named = "{ #{@named_imports.join(', ')} }"
|
235
|
+
line = "#{@declaration_keyword} #{prefix}#{named} #{equals} " \
|
209
236
|
"#{value}"
|
210
237
|
return line unless line_too_long?(line, max_line_length)
|
211
238
|
|
212
|
-
named = "{\n#{tab}#{named_imports.join(",\n#{tab}")},\n}"
|
213
|
-
"#{declaration_keyword} #{prefix}#{named} #{equals} #{value}"
|
239
|
+
named = "{\n#{tab}#{@named_imports.join(",\n#{tab}")},\n}"
|
240
|
+
"#{@declaration_keyword} #{prefix}#{named} #{equals} #{value}"
|
214
241
|
end
|
215
242
|
|
216
243
|
def clear_import_string_cache
|
@@ -0,0 +1,175 @@
|
|
1
|
+
module ImportJS
|
2
|
+
# Class that sorts ImportStatements as they are pushed in
|
3
|
+
class ImportStatements
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
STYLE_IMPORT = :import
|
7
|
+
STYLE_CONST = :const
|
8
|
+
STYLE_VAR = :var
|
9
|
+
STYLE_CUSTOM = :custom
|
10
|
+
|
11
|
+
# Order is significant here
|
12
|
+
STYLES = [STYLE_IMPORT, STYLE_CONST, STYLE_VAR, STYLE_CUSTOM].freeze
|
13
|
+
|
14
|
+
PATH_TYPE_PACKAGE = :package
|
15
|
+
PATH_TYPE_NON_RELATIVE = :non_relative
|
16
|
+
PATH_TYPE_RELATIVE = :relative
|
17
|
+
|
18
|
+
# Order is significant here
|
19
|
+
PATH_TYPES = [
|
20
|
+
PATH_TYPE_PACKAGE,
|
21
|
+
PATH_TYPE_NON_RELATIVE,
|
22
|
+
PATH_TYPE_RELATIVE,
|
23
|
+
].freeze
|
24
|
+
|
25
|
+
GROUPINGS_ARRAY = STYLES.map do |style|
|
26
|
+
PATH_TYPES.map do |location|
|
27
|
+
"#{style} #{location}"
|
28
|
+
end
|
29
|
+
end.flatten.freeze
|
30
|
+
|
31
|
+
GROUPINGS = Hash[
|
32
|
+
GROUPINGS_ARRAY.each_with_index.map { |group, index| [group, index] }
|
33
|
+
].freeze
|
34
|
+
|
35
|
+
# @param config [ImportJS::Configuration]
|
36
|
+
# @param imports [Hash]
|
37
|
+
def initialize(config, imports = {})
|
38
|
+
@config = config
|
39
|
+
@imports = imports
|
40
|
+
end
|
41
|
+
|
42
|
+
def each
|
43
|
+
return enum_for(:each) unless block_given?
|
44
|
+
|
45
|
+
@imports.each do |_, import_statement|
|
46
|
+
yield import_statement
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def clone
|
51
|
+
ImportStatements.new(@config, @imports.clone)
|
52
|
+
end
|
53
|
+
|
54
|
+
# @param import_statement [ImportJS::ImportStatement]
|
55
|
+
# @return [ImportJS::ImportStatements]
|
56
|
+
def push(import_statement)
|
57
|
+
if @imports[import_statement.path]
|
58
|
+
# Import already exists, so this line is likely one of a named imports
|
59
|
+
# pair. Combine it into the same ImportStatement.
|
60
|
+
@imports[import_statement.path].merge(import_statement)
|
61
|
+
else
|
62
|
+
# This is a new import, so we just add it to the hash.
|
63
|
+
@imports[import_statement.path] = import_statement
|
64
|
+
end
|
65
|
+
|
66
|
+
self # for chaining
|
67
|
+
end
|
68
|
+
alias << push
|
69
|
+
|
70
|
+
# @param variable_names [Array<String>]
|
71
|
+
# @return [ImportJS::ImportStatements]
|
72
|
+
def delete_variables!(variable_names)
|
73
|
+
@imports.reject! do |_, import_statement|
|
74
|
+
variable_names.each do |variable_name|
|
75
|
+
import_statement.delete_variable!(variable_name)
|
76
|
+
end
|
77
|
+
import_statement.empty?
|
78
|
+
end
|
79
|
+
|
80
|
+
self # for chaining
|
81
|
+
end
|
82
|
+
|
83
|
+
# Convert the import statements into an array of strings, with an empty
|
84
|
+
# string between each group.
|
85
|
+
# @return [Array<String>]
|
86
|
+
def to_a
|
87
|
+
max_line_length = @config.get('max_line_length')
|
88
|
+
tab = @config.get('tab')
|
89
|
+
|
90
|
+
strings = []
|
91
|
+
to_groups.each do |group|
|
92
|
+
group.each do |import_statement|
|
93
|
+
strings.concat(
|
94
|
+
import_statement.to_import_strings(max_line_length, tab))
|
95
|
+
end
|
96
|
+
strings << '' # Add a blank line between groups.
|
97
|
+
end
|
98
|
+
|
99
|
+
# We don't want to include a trailing newline at the end of all the
|
100
|
+
# groups here.
|
101
|
+
strings.pop if strings.last == ''
|
102
|
+
|
103
|
+
strings
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
# Sort the import statements by path and group them based on our heuristic
|
109
|
+
# of style and path type.
|
110
|
+
# @return [Array<Array<ImportJS::ImportStatement>>]
|
111
|
+
def to_groups
|
112
|
+
groups = []
|
113
|
+
|
114
|
+
imports_array = @imports.values
|
115
|
+
|
116
|
+
# There's a chance we have duplicate imports (can happen when switching
|
117
|
+
# declaration_keyword for instance). By first sorting imports so that new
|
118
|
+
# ones are first, then removing duplicates, we guarantee that we delete
|
119
|
+
# the old ones that are now redundant.
|
120
|
+
partitioned = imports_array.partition do |import_statement|
|
121
|
+
!import_statement.parsed_and_untouched?
|
122
|
+
end.flatten.uniq(&:to_normalized).sort_by(&:to_normalized)
|
123
|
+
|
124
|
+
package_dependencies = @config.package_dependencies
|
125
|
+
partitioned.each do |import_statement|
|
126
|
+
# Figure out what group to put this import statement in
|
127
|
+
group_index = import_statement_group_index(
|
128
|
+
import_statement, package_dependencies)
|
129
|
+
|
130
|
+
# Add the import statement to the group
|
131
|
+
groups[group_index] ||= []
|
132
|
+
groups[group_index] << import_statement
|
133
|
+
end
|
134
|
+
|
135
|
+
groups.compact! unless groups.empty?
|
136
|
+
groups
|
137
|
+
end
|
138
|
+
|
139
|
+
# @param import_statement [ImportJS::ImportStatement]
|
140
|
+
# @param package_dependencies [Array<String>]
|
141
|
+
# @return [Number]
|
142
|
+
def import_statement_group_index(import_statement, package_dependencies)
|
143
|
+
style = import_statement_style(import_statement)
|
144
|
+
path_type = import_statement_path_type(
|
145
|
+
import_statement, package_dependencies)
|
146
|
+
|
147
|
+
GROUPINGS["#{style} #{path_type}"]
|
148
|
+
end
|
149
|
+
|
150
|
+
# Determine import statement style
|
151
|
+
# @param import_statement [ImportJS::ImportStatement]
|
152
|
+
# @return [String] 'import', 'const', 'var', or 'custom'
|
153
|
+
def import_statement_style(import_statement)
|
154
|
+
return STYLE_IMPORT if import_statement.declaration_keyword == 'import'
|
155
|
+
|
156
|
+
if import_statement.import_function == 'require'
|
157
|
+
return STYLE_CONST if import_statement.declaration_keyword == 'const'
|
158
|
+
return STYLE_VAR if import_statement.declaration_keyword == 'var'
|
159
|
+
end
|
160
|
+
|
161
|
+
STYLE_CUSTOM
|
162
|
+
end
|
163
|
+
|
164
|
+
# Determine import path type
|
165
|
+
# @param import_statement [ImportJS::ImportStatement]
|
166
|
+
# @param package_dependencies [Array<String>]
|
167
|
+
# @return [String] 'package, 'non-relative', 'relative'
|
168
|
+
def import_statement_path_type(import_statement, package_dependencies)
|
169
|
+
path = import_statement.path
|
170
|
+
return PATH_TYPE_RELATIVE if path.start_with?('.')
|
171
|
+
return PATH_TYPE_PACKAGE if package_dependencies.include?(path)
|
172
|
+
PATH_TYPE_NON_RELATIVE
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
data/lib/import_js/importer.rb
CHANGED
@@ -1,14 +1,10 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'open3'
|
3
|
+
require 'set'
|
4
|
+
require 'strscan'
|
3
5
|
|
4
6
|
module ImportJS
|
5
7
|
class Importer
|
6
|
-
REGEX_USE_STRICT = /(['"])use strict\1;?/
|
7
|
-
REGEX_SINGLE_LINE_COMMENT = %r{\A\s*//}
|
8
|
-
REGEX_MULTI_LINE_COMMENT_START = %r{\A\s*/\*}
|
9
|
-
REGEX_MULTI_LINE_COMMENT_END = %r{\*/}
|
10
|
-
REGEX_WHITESPACE_ONLY = /\A\s*\Z/
|
11
|
-
|
12
8
|
def initialize(editor = VIMEditor.new)
|
13
9
|
@editor = editor
|
14
10
|
end
|
@@ -31,10 +27,9 @@ module ImportJS
|
|
31
27
|
|
32
28
|
maintain_cursor_position do
|
33
29
|
old_imports = find_current_imports
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
old_imports[:imports_start_at])
|
30
|
+
import_statement = js_module.to_import_statement(variable_name, @config)
|
31
|
+
old_imports[:imports] << import_statement
|
32
|
+
replace_imports(old_imports[:range], old_imports[:imports])
|
38
33
|
end
|
39
34
|
end
|
40
35
|
|
@@ -43,16 +38,11 @@ module ImportJS
|
|
43
38
|
js_modules = []
|
44
39
|
variable_name = @editor.current_word
|
45
40
|
time do
|
46
|
-
js_modules =
|
47
|
-
end
|
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}`")
|
41
|
+
js_modules = find_js_modules_for(variable_name)
|
53
42
|
end
|
54
43
|
|
55
|
-
js_module =
|
44
|
+
js_module = resolve_module_using_current_imports(
|
45
|
+
js_modules, variable_name)
|
56
46
|
|
57
47
|
unless js_module
|
58
48
|
# The current word is not mappable to one of the JS modules that we
|
@@ -83,38 +73,48 @@ module ImportJS
|
|
83
73
|
reload_config
|
84
74
|
eslint_result = run_eslint_command
|
85
75
|
|
86
|
-
unused_variables =
|
87
|
-
undefined_variables =
|
76
|
+
unused_variables = Set.new
|
77
|
+
undefined_variables = Set.new
|
88
78
|
|
89
79
|
eslint_result.each do |line|
|
90
80
|
match = REGEX_ESLINT_RESULT.match(line)
|
91
81
|
next unless match
|
92
82
|
if match[:type] == 'is defined but never used'
|
93
|
-
unused_variables
|
83
|
+
unused_variables.add match[:variable_name]
|
94
84
|
else
|
95
|
-
undefined_variables
|
85
|
+
undefined_variables.add match[:variable_name]
|
96
86
|
end
|
97
87
|
end
|
98
88
|
|
99
|
-
unused_variables.uniq!
|
100
|
-
undefined_variables.uniq!
|
101
|
-
|
102
89
|
old_imports = find_current_imports
|
103
|
-
new_imports = old_imports[:imports].
|
104
|
-
|
105
|
-
import_statement.delete_variable(unused_variable)
|
106
|
-
end
|
107
|
-
import_statement.empty?
|
108
|
-
end
|
90
|
+
new_imports = old_imports[:imports].clone
|
91
|
+
new_imports.delete_variables!(unused_variables.to_a)
|
109
92
|
|
110
93
|
undefined_variables.each do |variable|
|
111
94
|
js_module = find_one_js_module(variable)
|
112
|
-
|
95
|
+
next unless js_module
|
96
|
+
new_imports << js_module.to_import_statement(variable, @config)
|
97
|
+
end
|
98
|
+
|
99
|
+
replace_imports(old_imports[:range], new_imports)
|
100
|
+
end
|
101
|
+
|
102
|
+
def rewrite_imports
|
103
|
+
reload_config
|
104
|
+
|
105
|
+
old_imports = find_current_imports
|
106
|
+
new_imports = old_imports[:imports].clone
|
107
|
+
|
108
|
+
old_imports[:imports].each do |import|
|
109
|
+
import.variables.each do |variable|
|
110
|
+
js_module = resolve_module_using_current_imports(
|
111
|
+
find_js_modules_for(variable), variable)
|
112
|
+
next unless js_module
|
113
|
+
new_imports << js_module.to_import_statement(variable, @config)
|
114
|
+
end
|
113
115
|
end
|
114
116
|
|
115
|
-
replace_imports(old_imports[:
|
116
|
-
new_imports,
|
117
|
-
old_imports[:imports_start_at])
|
117
|
+
replace_imports(old_imports[:range], new_imports)
|
118
118
|
end
|
119
119
|
|
120
120
|
private
|
@@ -158,11 +158,11 @@ module ImportJS
|
|
158
158
|
stdin_data: @editor.current_file_content)
|
159
159
|
|
160
160
|
if ESLINT_STDOUT_ERROR_REGEXES.any? { |regex| out =~ regex }
|
161
|
-
|
161
|
+
raise ParseError.new, out
|
162
162
|
end
|
163
163
|
|
164
164
|
if ESLINT_STDERR_ERROR_REGEXES.any? { |regex| err =~ regex }
|
165
|
-
|
165
|
+
raise ParseError.new, err
|
166
166
|
end
|
167
167
|
|
168
168
|
out.split("\n")
|
@@ -173,7 +173,7 @@ module ImportJS
|
|
173
173
|
def find_one_js_module(variable_name)
|
174
174
|
js_modules = []
|
175
175
|
time do
|
176
|
-
js_modules =
|
176
|
+
js_modules = find_js_modules_for(variable_name)
|
177
177
|
end
|
178
178
|
if js_modules.empty?
|
179
179
|
message(
|
@@ -184,59 +184,30 @@ module ImportJS
|
|
184
184
|
resolve_one_js_module(js_modules, variable_name)
|
185
185
|
end
|
186
186
|
|
187
|
-
# Add new import to the block of imports, wrapping at the max line length
|
188
|
-
# @param variable_name [String]
|
189
|
-
# @param js_module [ImportJS::JSModule]
|
190
|
-
# @param imports [Array<ImportJS::ImportStatement>]
|
191
|
-
def inject_js_module(variable_name, js_module, imports)
|
192
|
-
import = imports.find do |an_import|
|
193
|
-
an_import.path == js_module.import_path
|
194
|
-
end
|
195
|
-
|
196
|
-
if import
|
197
|
-
import.declaration_keyword = @config.get(
|
198
|
-
'declaration_keyword', from_file: js_module.file_path)
|
199
|
-
import.import_function = @config.get(
|
200
|
-
'import_function', from_file: js_module.file_path)
|
201
|
-
if js_module.has_named_exports
|
202
|
-
import.inject_named_import(variable_name)
|
203
|
-
else
|
204
|
-
import.set_default_import(variable_name)
|
205
|
-
end
|
206
|
-
else
|
207
|
-
imports.unshift(js_module.to_import_statement(variable_name, @config))
|
208
|
-
end
|
209
|
-
|
210
|
-
# Remove duplicate import statements
|
211
|
-
imports.uniq!(&:to_normalized)
|
212
|
-
end
|
213
|
-
|
214
187
|
# @param imports [Array<ImportJS::ImportStatement>]
|
215
188
|
# @return [String]
|
216
189
|
def generate_import_strings(import_statements)
|
217
190
|
import_statements.map do |import|
|
218
|
-
import.to_import_strings(@
|
191
|
+
import.to_import_strings(@config.get('max_line_length'),
|
192
|
+
@config.get('tab'))
|
219
193
|
end.flatten.sort
|
220
194
|
end
|
221
195
|
|
222
|
-
# @param
|
223
|
-
# @param new_imports [
|
224
|
-
|
225
|
-
|
226
|
-
imports_end_at = old_imports_lines + imports_start_at
|
196
|
+
# @param old_imports_range [Range]
|
197
|
+
# @param new_imports [ImportJS::ImportStatements]
|
198
|
+
def replace_imports(old_imports_range, new_imports)
|
199
|
+
import_strings = new_imports.to_a
|
227
200
|
|
228
201
|
# Ensure that there is a blank line after the block of all imports
|
229
|
-
if
|
230
|
-
!@editor.read_line(
|
231
|
-
@editor.append_line(
|
202
|
+
if old_imports_range.size + import_strings.length > 0 &&
|
203
|
+
!@editor.read_line(old_imports_range.last + 1).strip.empty?
|
204
|
+
@editor.append_line(old_imports_range.last, '')
|
232
205
|
end
|
233
206
|
|
234
|
-
import_strings = generate_import_strings(new_imports)
|
235
|
-
|
236
207
|
# Find old import strings so we can compare with the new import strings
|
237
208
|
# and see if anything has changed.
|
238
209
|
old_import_strings = []
|
239
|
-
|
210
|
+
old_imports_range.each do |line_index|
|
240
211
|
old_import_strings << @editor.read_line(line_index + 1)
|
241
212
|
end
|
242
213
|
|
@@ -245,97 +216,72 @@ module ImportJS
|
|
245
216
|
return if import_strings == old_import_strings
|
246
217
|
|
247
218
|
# Delete old imports, then add the modified list back in.
|
248
|
-
|
219
|
+
old_imports_range.each do
|
220
|
+
@editor.delete_line(1 + old_imports_range.first)
|
221
|
+
end
|
249
222
|
import_strings.reverse_each do |import_string|
|
250
223
|
# We need to add each line individually because the Vim buffer will
|
251
224
|
# convert newline characters to `~@`.
|
252
|
-
import_string.
|
253
|
-
|
225
|
+
if import_string.include? "\n"
|
226
|
+
import_string.split("\n").reverse_each do |line|
|
227
|
+
@editor.append_line(old_imports_range.first, line)
|
228
|
+
end
|
229
|
+
else
|
230
|
+
@editor.append_line(old_imports_range.first, import_string)
|
254
231
|
end
|
255
232
|
end
|
256
233
|
end
|
257
234
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
inside_multi_line_comment = !(line =~ REGEX_MULTI_LINE_COMMENT_END)
|
272
|
-
next
|
273
|
-
end
|
274
|
-
|
275
|
-
if line =~ REGEX_USE_STRICT || line =~ REGEX_SINGLE_LINE_COMMENT
|
276
|
-
matched_non_whitespace_line = true
|
277
|
-
imports_start_line_index = line_index + 1
|
278
|
-
next
|
279
|
-
end
|
280
|
-
|
281
|
-
if line =~ REGEX_WHITESPACE_ONLY
|
282
|
-
imports_start_line_index = line_index + 1
|
283
|
-
next
|
284
|
-
end
|
285
|
-
|
286
|
-
break
|
287
|
-
end
|
288
|
-
|
289
|
-
# We don't want to skip over blocks that are only whitespace
|
290
|
-
return imports_start_line_index if matched_non_whitespace_line
|
291
|
-
0
|
292
|
-
end
|
235
|
+
REGEX_SKIP_SECTION = %r{
|
236
|
+
\s* # preceding whitespace
|
237
|
+
(?:
|
238
|
+
(['"])use\sstrict\1;? # 'use strict';
|
239
|
+
|
|
240
|
+
//.* # single-line comment
|
241
|
+
|
|
242
|
+
/\* # open multi-line comment
|
243
|
+
(?:\n|.)*? # inside of multi-line comment
|
244
|
+
\*/ # close multi-line comment
|
245
|
+
)? # ? b/c we want to match on only whitespace
|
246
|
+
\n # end of line
|
247
|
+
}x
|
293
248
|
|
294
249
|
# @return [Hash]
|
295
250
|
def find_current_imports
|
296
|
-
|
297
|
-
|
298
|
-
newline_count: 0,
|
299
|
-
imports_start_at: find_imports_start_line_index,
|
300
|
-
}
|
251
|
+
imports_start_at = 0
|
252
|
+
newline_count = 0
|
301
253
|
|
302
|
-
|
303
|
-
|
304
|
-
(
|
305
|
-
|
306
|
-
break if line.strip.empty?
|
307
|
-
potential_import_lines << line
|
254
|
+
scanner = StringScanner.new(@editor.current_file_content)
|
255
|
+
skipped = ''
|
256
|
+
while skip_section = scanner.scan(REGEX_SKIP_SECTION)
|
257
|
+
skipped += skip_section
|
308
258
|
end
|
309
259
|
|
310
|
-
# We
|
311
|
-
|
312
|
-
|
260
|
+
# We don't want to skip over blocks that are only whitespace
|
261
|
+
if skipped =~ /\A(\s*\n)+\Z/m
|
262
|
+
scanner = StringScanner.new(@editor.current_file_content)
|
263
|
+
else
|
264
|
+
imports_start_at += skipped.count("\n")
|
265
|
+
end
|
313
266
|
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
potential_imports_blob.scan(/^.*?;/m).each do |potential_import|
|
318
|
-
import_statement = ImportStatement.parse(potential_import)
|
267
|
+
imports = ImportStatements.new(@config)
|
268
|
+
while potential_import = scanner.scan(/(^\s*\n)*^.*?;\n/m)
|
269
|
+
import_statement = ImportStatement.parse(potential_import.strip)
|
319
270
|
break unless import_statement
|
320
271
|
|
321
|
-
|
322
|
-
|
323
|
-
# pair. Combine it into the same ImportStatement.
|
324
|
-
imports[import_statement.path].merge(import_statement)
|
325
|
-
else
|
326
|
-
# This is a new import, so we just add it to the hash.
|
327
|
-
imports[import_statement.path] = import_statement
|
328
|
-
end
|
329
|
-
|
330
|
-
result[:newline_count] += potential_import.scan(/\n/).length + 1
|
272
|
+
imports << import_statement
|
273
|
+
newline_count += potential_import.scan(/\n/).length
|
331
274
|
end
|
332
|
-
|
333
|
-
|
275
|
+
|
276
|
+
{
|
277
|
+
imports: imports,
|
278
|
+
range: imports_start_at...(imports_start_at + newline_count),
|
279
|
+
}
|
334
280
|
end
|
335
281
|
|
336
282
|
# @param variable_name [String]
|
337
283
|
# @return [Array]
|
338
|
-
def
|
284
|
+
def find_js_modules_for(variable_name)
|
339
285
|
path_to_current_file = @editor.path_to_current_file
|
340
286
|
|
341
287
|
alias_module = @config.resolve_alias(variable_name, path_to_current_file)
|
@@ -352,8 +298,8 @@ module ImportJS
|
|
352
298
|
if lookup_path == ''
|
353
299
|
# If lookup_path is an empty string, the `find` command will not work
|
354
300
|
# as desired so we bail early.
|
355
|
-
|
356
|
-
|
301
|
+
raise FindError.new,
|
302
|
+
"lookup path cannot be empty (#{lookup_path.inspect})"
|
357
303
|
end
|
358
304
|
|
359
305
|
find_command = %W[
|
@@ -364,7 +310,7 @@ module ImportJS
|
|
364
310
|
command = "#{find_command} | #{egrep_command}"
|
365
311
|
out, err = Open3.capture3(command)
|
366
312
|
|
367
|
-
|
313
|
+
raise FindError.new, err unless err == ''
|
368
314
|
|
369
315
|
matched_modules.concat(
|
370
316
|
out.split("\n").map do |f|
|
@@ -443,15 +389,35 @@ module ImportJS
|
|
443
389
|
# @param js_modules [Array]
|
444
390
|
# @param variable_name [String]
|
445
391
|
# @return [ImportJS::JSModule]
|
446
|
-
def
|
392
|
+
def resolve_module_using_current_imports(js_modules, variable_name)
|
447
393
|
return js_modules.first if js_modules.length == 1
|
448
394
|
|
449
|
-
# Look
|
450
|
-
|
395
|
+
# Look at the current imports and grab what is already imported for the
|
396
|
+
# variable.
|
397
|
+
matching_import_statement = find_current_imports[:imports].find do |ist|
|
398
|
+
next true if variable_name == ist.default_import
|
399
|
+
next false unless ist.named_imports
|
400
|
+
ist.named_imports.include?(variable_name)
|
401
|
+
end
|
402
|
+
|
403
|
+
if matching_import_statement
|
404
|
+
if js_modules.empty?
|
405
|
+
# We couldn't resolve any module for the variable. As a fallback, we
|
406
|
+
# can use the matching import statement. If that maps to a package
|
407
|
+
# dependency, we will still open the right file.
|
408
|
+
matched_module = JSModule.new(
|
409
|
+
import_path: matching_import_statement.path)
|
410
|
+
if matching_import_statement.named_imports?
|
411
|
+
matched_module.has_named_exports =
|
412
|
+
matching_import_statement.named_imports.include?(variable_name)
|
413
|
+
end
|
414
|
+
return matched_module
|
415
|
+
end
|
416
|
+
|
417
|
+
# Look for a module matching what is already imported
|
451
418
|
js_modules.each do |js_module|
|
452
|
-
|
453
|
-
|
454
|
-
return js_module if ist.path == js_module.import_path
|
419
|
+
return js_module if matching_import_statement.path ==
|
420
|
+
js_module.import_path
|
455
421
|
end
|
456
422
|
end
|
457
423
|
|
data/lib/import_js/js_module.rb
CHANGED
@@ -16,6 +16,7 @@ module ImportJS
|
|
16
16
|
# e.g. ['.js', '.jsx']
|
17
17
|
# @param make_relative_to [String|nil] a path to a different file which the
|
18
18
|
# resulting import path should be relative to.
|
19
|
+
# @param strip_from_path [String]
|
19
20
|
def self.construct(lookup_path: nil,
|
20
21
|
relative_file_path: nil,
|
21
22
|
strip_file_extensions: nil,
|
@@ -30,13 +31,12 @@ module ImportJS
|
|
30
31
|
|
31
32
|
return unless import_path
|
32
33
|
|
33
|
-
import_path
|
34
|
-
%r{^#{Regexp.escape(js_module.lookup_path)}/}, '')
|
34
|
+
import_path.sub!(%r{^#{Regexp.escape(js_module.lookup_path)}/}, '')
|
35
35
|
|
36
36
|
js_module.import_path = import_path
|
37
37
|
js_module.main_file = main_file
|
38
38
|
js_module.make_relative_to(make_relative_to) if make_relative_to
|
39
|
-
js_module.strip_from_path(strip_from_path) unless make_relative_to
|
39
|
+
js_module.strip_from_path!(strip_from_path) unless make_relative_to
|
40
40
|
js_module
|
41
41
|
end
|
42
42
|
|
@@ -101,15 +101,18 @@ module ImportJS
|
|
101
101
|
# @param make_relative_to [String]
|
102
102
|
def make_relative_to(make_relative_to)
|
103
103
|
return unless lookup_path
|
104
|
+
|
105
|
+
# Prevent mutating the argument that was passed in
|
106
|
+
make_relative_to = make_relative_to.dup
|
107
|
+
|
104
108
|
# First, strip out any absolute path up until the current directory
|
105
|
-
make_relative_to
|
109
|
+
make_relative_to.sub!("#{Dir.pwd}/", '')
|
106
110
|
|
107
111
|
# Ignore if the file to relate to is part of a different lookup_path
|
108
112
|
return unless make_relative_to.start_with? lookup_path
|
109
113
|
|
110
114
|
# Strip out the lookup_path
|
111
|
-
make_relative_to
|
112
|
-
%r{^#{Regexp.escape(lookup_path)}/}, '')
|
115
|
+
make_relative_to.sub!(%r{^#{Regexp.escape(lookup_path)}/}, '')
|
113
116
|
|
114
117
|
path = Pathname.new(import_path).relative_path_from(
|
115
118
|
Pathname.new(File.dirname(make_relative_to))
|
@@ -122,9 +125,9 @@ module ImportJS
|
|
122
125
|
end
|
123
126
|
|
124
127
|
# @param prefix [String]
|
125
|
-
def strip_from_path(prefix)
|
128
|
+
def strip_from_path!(prefix)
|
126
129
|
return unless prefix
|
127
|
-
|
130
|
+
import_path.sub!(/^#{Regexp.escape(prefix)}/, '')
|
128
131
|
end
|
129
132
|
|
130
133
|
# @return [String] a readable description of the module
|
@@ -171,18 +174,20 @@ module ImportJS
|
|
171
174
|
# @param config [ImportJS::Configuration]
|
172
175
|
# @return [ImportJS::ImportStatement]
|
173
176
|
def to_import_statement(variable_name, config)
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
statement.default_import = variable_name
|
179
|
-
end
|
180
|
-
statement.path = import_path
|
181
|
-
statement.declaration_keyword = config.get('declaration_keyword',
|
182
|
-
from_file: file_path)
|
183
|
-
statement.import_function = config.get('import_function',
|
184
|
-
from_file: file_path)
|
177
|
+
if has_named_exports
|
178
|
+
named_imports = [variable_name]
|
179
|
+
else
|
180
|
+
default_import = variable_name
|
185
181
|
end
|
182
|
+
|
183
|
+
ImportStatement.new(
|
184
|
+
declaration_keyword:
|
185
|
+
config.get('declaration_keyword', from_file: file_path),
|
186
|
+
default_import: default_import,
|
187
|
+
import_function: config.get('import_function', from_file: file_path),
|
188
|
+
named_imports: named_imports,
|
189
|
+
path: import_path
|
190
|
+
)
|
186
191
|
end
|
187
192
|
end
|
188
193
|
end
|
data/lib/import_js/version.rb
CHANGED
data/lib/import_js/vim_editor.rb
CHANGED
@@ -110,19 +110,6 @@ module ImportJS
|
|
110
110
|
selected_index - 1
|
111
111
|
end
|
112
112
|
|
113
|
-
# Get the preferred max length of a line
|
114
|
-
# @return [Number?]
|
115
|
-
def max_line_length
|
116
|
-
get_number('&textwidth')
|
117
|
-
end
|
118
|
-
|
119
|
-
# @return [String] shiftwidth number of spaces if expandtab is not set,
|
120
|
-
# otherwise `\t`
|
121
|
-
def tab
|
122
|
-
return "\t" unless expand_tab?
|
123
|
-
' ' * (shift_width || 2)
|
124
|
-
end
|
125
|
-
|
126
113
|
private
|
127
114
|
|
128
115
|
# Check for the presence of a setting such as:
|
@@ -147,21 +134,5 @@ module ImportJS
|
|
147
134
|
def get_number(name)
|
148
135
|
exists?(name) ? VIM.evaluate(name).to_i : nil
|
149
136
|
end
|
150
|
-
|
151
|
-
# @param name [String]
|
152
|
-
# @return [Boolean?]
|
153
|
-
def get_bool(name)
|
154
|
-
exists?(name) ? VIM.evaluate(name).to_i != 0 : nil
|
155
|
-
end
|
156
|
-
|
157
|
-
# @return [Boolean?]
|
158
|
-
def expand_tab?
|
159
|
-
get_bool('&expandtab')
|
160
|
-
end
|
161
|
-
|
162
|
-
# @return [Number?]
|
163
|
-
def shift_width
|
164
|
-
get_number('&shiftwidth')
|
165
|
-
end
|
166
137
|
end
|
167
138
|
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
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henric Trotzig
|
@@ -43,10 +43,12 @@ files:
|
|
43
43
|
- lib/import_js/configuration.rb
|
44
44
|
- lib/import_js/emacs_editor.rb
|
45
45
|
- lib/import_js/import_statement.rb
|
46
|
+
- lib/import_js/import_statements.rb
|
46
47
|
- lib/import_js/importer.rb
|
47
48
|
- lib/import_js/js_module.rb
|
48
49
|
- lib/import_js/version.rb
|
49
50
|
- lib/import_js/vim_editor.rb
|
51
|
+
- lib/vim_import_js.rb
|
50
52
|
homepage: http://rubygems.org/gems/import_js
|
51
53
|
licenses:
|
52
54
|
- MIT
|