Skip to content

Commit

Permalink
Add use_relative_paths configuration option
Browse files Browse the repository at this point in the history
By setting this to `true`, imports will be resolved relatively to the
file you are currently looking at, under these circumstances:

 - The file you are currently in is in the same lookup_path as the
   module you are trying to import
 - The module you are resolving is not a package.json dependency /
   located in node_modules
 - The module you are importing is not an alias.

I'm not too happy with how the JSModule constructor ended up after this
change, so I indent to follow up with some clean-up.
  • Loading branch information
trotzig committed Jan 10, 2016
1 parent 15c5c72 commit 994f70d
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 6 deletions.
3 changes: 2 additions & 1 deletion lib/import_js/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ module ImportJS
'declaration_keyword' => 'import',
'excludes' => [],
'lookup_paths' => ['.'],
'strip_file_extensions' => ['.js', '.jsx']
'strip_file_extensions' => ['.js', '.jsx'],
'use_relative_paths' => false
}

# Class that initializes configuration from a .importjs.json file
Expand Down
10 changes: 7 additions & 3 deletions lib/import_js/importer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -241,11 +241,11 @@ def find_current_imports
# @param variable_name [String]
# @return [Array]
def find_js_modules(variable_name)
path_to_current_file = @editor.path_to_current_file
if alias_module = @config.resolve_alias(variable_name,
@editor.path_to_current_file)
path_to_current_file)
return [alias_module]
end

egrep_command =
"egrep -i \"(/|^)#{formatted_to_regex(variable_name)}(/index)?(/package)?\.js.*\""
matched_modules = []
Expand All @@ -260,7 +260,11 @@ def find_js_modules(variable_name)
js_module = ImportJS::JSModule.new(
lookup_path: lookup_path,
relative_file_path: f,
strip_file_extensions: @config.get('strip_file_extensions'))
strip_file_extensions: @config.get('strip_file_extensions'),
make_relative_to: @config.get('use_relative_paths') &&
path_to_current_file
)

next if js_module.skip
js_module
end.compact
Expand Down
22 changes: 21 additions & 1 deletion lib/import_js/js_module.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require 'pathname'

module ImportJS
# Class that represents a js module found in the file system
class JSModule
Expand All @@ -13,9 +15,12 @@ class JSModule
# the project root.
# @param strip_file_extensions [Array] a list of file extensions to strip,
# e.g. ['.js', '.jsx']
# @param make_relative_to [String|nil] a path to a different file which the
# resulting import path should be relative to.
def initialize(lookup_path:,
relative_file_path:,
strip_file_extensions:)
strip_file_extensions:,
make_relative_to: nil)
@lookup_path = lookup_path
@file_path = relative_file_path
if relative_file_path.end_with? '/package.json'
Expand All @@ -39,6 +44,21 @@ def initialize(lookup_path:,

if lookup_path
@import_path = @import_path.sub("#{@lookup_path}\/", '') # remove path prefix
if make_relative_to
make_relative_to = make_relative_to.sub(Dir.pwd + "\/", '')
if make_relative_to.start_with? @lookup_path
make_relative_to_folder = Pathname.new(File.dirname(
make_relative_to.sub("#{@lookup_path}\/", '')
))
path = Pathname.new(@import_path).relative_path_from(
make_relative_to_folder
).to_s
unless path.start_with?('.')
path = './' + path
end
@import_path = path
end
end
end
end

Expand Down
48 changes: 48 additions & 0 deletions spec/import_js/importer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1281,6 +1281,54 @@ def self.current_selection=(index)
end
end
end

context 'with `use_relative_paths=true`' do
let(:existing_files) { ['bar/foo.jsx'] }
let(:text) { <<-EOS.strip }
foo
EOS

before do
allow_any_instance_of(ImportJS::VIMEditor)
.to receive(:path_to_current_file)
.and_return(path_to_current_file)
end

subject do
described_class.new.import
VIM::Buffer.current_buffer.to_s
end

let(:configuration) do
{
'use_relative_paths' => true
}
end

context 'when the current file is in the same lookup_path' do
let(:path_to_current_file) { File.join(@tmp_dir, 'bar/current.js') }

it 'uses a relative import path' do
expect(subject).to eq(<<-EOS.strip)
import foo from './foo';
foo
EOS
end
end

context 'when the current file is not in the same lookup_path' do
let(:path_to_current_file) { '/foo/bar/current.js' }

it 'does not use a relative import path' do
expect(subject).to eq(<<-EOS.strip)
import foo from 'bar/foo';
foo
EOS
end
end
end
end
end

Expand Down
47 changes: 46 additions & 1 deletion spec/import_js/js_module_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
describe ImportJS::JSModule do
let(:lookup_path) { 'app' }
let(:relative_file_path) { 'app/lib/foo.js' }
let(:make_relative_to) { nil }
let(:strip_file_extensions) { ['.js'] }

subject do
described_class.new(
lookup_path: lookup_path,
relative_file_path: relative_file_path,
strip_file_extensions: strip_file_extensions
strip_file_extensions: strip_file_extensions,
make_relative_to: make_relative_to
)
end

Expand Down Expand Up @@ -58,5 +61,47 @@
end
end
end

context 'when asked to produce an import path relative to another file' do
context 'and the other file is in the same folder' do
let(:make_relative_to) { 'app/lib/bar.js' }

it 'produces a correct relative path' do
expect(subject.import_path).to eq('./foo')
end
end

context 'and the other file is in a parent folder' do
let(:make_relative_to) { 'app/bar.js' }

it 'produces a correct relative path' do
expect(subject.import_path).to eq('./lib/foo')
end
end

context 'and the other file is in a sibling folder' do
let(:make_relative_to) { 'app/foo/bar.js' }

it 'produces a correct relative path' do
expect(subject.import_path).to eq('../lib/foo')
end
end

context 'and the other file is in a child of a sibling folder' do
let(:make_relative_to) { 'app/foo/gas/bar.js' }

it 'produces a correct relative path' do
expect(subject.import_path).to eq('../../lib/foo')
end
end

context 'and the other file is in a different lookup_path' do
let(:make_relative_to) { 'spec/foo/gas/bar.js' }

it 'does not create a relative path' do
expect(subject.import_path).to eq('lib/foo')
end
end
end
end
end

0 comments on commit 994f70d

Please sign in to comment.