import_js 0.3.1 → 0.4.0

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: c90724e922f7ebecab12977097f1b867d83d8f74
4
- data.tar.gz: 43cc4828550165c17ca8b07b142c5e033fbbb31f
3
+ metadata.gz: a2a0036427b0f66373fcbc6fda702570d501f281
4
+ data.tar.gz: 9c798047e26eb9189e169c5395ed1bd41b03e2fc
5
5
  SHA512:
6
- metadata.gz: c6f3b02306c7c21ccc09b13e7246d2c8ddb7c78f05f149d2644b73d1ce8d731d4349e54f68d52bc79b1558d07aa94aba5fe7a809f9f4137410f9cfccd0d4225e
7
- data.tar.gz: 105ab5859eaef7bd8d3bd5b31a0725c4000cf833743a786c7d6a1e9a5bac21bcbdc2de79580c565f74fde07a58f4467b004709031695a892d3468d4cc9304b2d
6
+ metadata.gz: 4eaed3ab7c8204e62a7b19bdad9cf002384f6797cd15fe6f6615763ebcda6f8cf607cbb3127f8c494082a53f84684c17e383544f897cd368ae0074101676dc5d
7
+ data.tar.gz: 43c8abdad3178c4df5c6f04a7030737daa9d2cb4e83cb777e6dbde088a5a43dffa2690ae13e1b1950ce915dc01f5252a75d4747883a9d0777124cf7353541e64
data/bin/import-js CHANGED
@@ -9,7 +9,7 @@ opts = Slop.parse do |o|
9
9
  o.bool '--goto', 'instead of importing, just print the path to a module'
10
10
  o.array '--selections', 'a list of resolved selections, e.g. Foo:0,Bar:1'
11
11
  o.string '--filename',
12
- 'a path to the file which contents are being passed in as stdin'
12
+ 'a path to the file which contents are being passed in as stdin'
13
13
  o.on '-v', '--version', 'print the current version' do
14
14
  puts ImportJS::VERSION
15
15
  exit
@@ -50,7 +50,7 @@ end
50
50
 
51
51
  # Print messages to stderr
52
52
  meta = {
53
- messages: editor.messages
53
+ messages: editor.messages,
54
54
  }
55
55
  ask = editor.ask_for_selections
56
56
  meta[:ask_for_selections] = ask unless ask.empty?
@@ -1,4 +1,5 @@
1
1
  module ImportJS
2
+ # This is the implementation of command line integration in Import-JS.
2
3
  class CommandLineEditor
3
4
  def initialize(lines, opts)
4
5
  @lines = lines
@@ -24,20 +25,14 @@ module ImportJS
24
25
  @goto = file_path
25
26
  end
26
27
 
27
- # @return [String]
28
- def goto
29
- @goto
30
- end
28
+ attr_reader :goto
31
29
 
32
30
  # @param str [String]
33
31
  def message(str)
34
32
  @messages << str
35
33
  end
36
34
 
37
- # @return [Array]
38
- def ask_for_selections
39
- @ask_for_selections
40
- end
35
+ attr_reader :ask_for_selections
41
36
 
42
37
  # @return [String]
43
38
  def current_file_content
@@ -110,7 +105,7 @@ module ImportJS
110
105
  else
111
106
  @ask_for_selections << {
112
107
  word: word,
113
- alternatives: alternatives
108
+ alternatives: alternatives,
114
109
  }
115
110
  nil
116
111
  end
@@ -1,42 +1,55 @@
1
+ # frozen_string_literal: true
1
2
  require 'json'
2
3
  require 'open3'
3
4
 
4
5
  module ImportJS
5
- CONFIG_FILE = '.importjs.json'
6
+ CONFIG_FILE = '.importjs.json'.freeze
6
7
 
7
8
  DEFAULT_CONFIG = {
8
9
  'aliases' => {},
9
10
  'declaration_keyword' => 'import',
11
+ 'named_exports' => {},
10
12
  'eslint_executable' => 'eslint',
11
13
  'excludes' => [],
12
14
  'ignore_package_prefixes' => [],
15
+ 'import_dev_dependencies' => false,
16
+ 'import_function' => 'require',
13
17
  'lookup_paths' => ['.'],
18
+ 'minimum_version' => '0.0.0',
14
19
  'strip_file_extensions' => ['.js', '.jsx'],
15
- 'use_relative_paths' => false
16
- }
20
+ 'strip_from_path' => nil,
21
+ 'use_relative_paths' => false,
22
+ }.freeze
17
23
 
18
24
  # Class that initializes configuration from a .importjs.json file
19
25
  class Configuration
20
- def initialize
21
- @config = DEFAULT_CONFIG.merge(load_config)
22
- end
26
+ def initialize(path_to_current_file)
27
+ @path_to_current_file = normalize_path(path_to_current_file)
28
+ @configs = []
29
+ user_config = load_config(CONFIG_FILE)
30
+ @configs.concat([user_config].flatten.reverse) if user_config
31
+ @configs << DEFAULT_CONFIG
23
32
 
24
- def refresh
25
- return if @config_time == config_file_last_modified
26
- @config = DEFAULT_CONFIG.merge(load_config)
33
+ check_current_version!
27
34
  end
28
35
 
29
36
  # @return [Object] a configuration value
30
- def get(key)
31
- @config[key]
37
+ def get(key, from_file: nil)
38
+ @configs.find do |config|
39
+ applies_to = config['applies_to'] || '*'
40
+ applies_from = config['applies_from'] || '*'
41
+ next unless config.key?(key)
42
+ File.fnmatch(normalize_path(applies_to), @path_to_current_file) &&
43
+ File.fnmatch(normalize_path(applies_from), normalize_path(from_file))
44
+ end[key]
32
45
  end
33
46
 
34
47
  # @param variable_name [String]
35
48
  # @param path_to_current_file [String?]
36
49
  # @return [ImportJS::JSModule?]
37
50
  def resolve_alias(variable_name, path_to_current_file)
38
- path = @config['aliases'][variable_name]
39
- return resolve_destructured_alias(variable_name) unless path
51
+ path = get('aliases')[variable_name]
52
+ return unless path
40
53
 
41
54
  path = path['path'] if path.is_a? Hash
42
55
 
@@ -44,21 +57,18 @@ module ImportJS
44
57
  path = path.sub(/\{filename\}/,
45
58
  File.basename(path_to_current_file, '.*'))
46
59
  end
47
- ImportJS::JSModule.new(lookup_path: nil,
48
- relative_file_path: path,
49
- strip_file_extensions: [])
60
+ ImportJS::JSModule.new(import_path: path)
50
61
  end
51
62
 
52
- def resolve_destructured_alias(variable_name)
53
- @config['aliases'].each do |_, path|
54
- next if path.is_a? String
55
- if (path['destructure'] || []).include?(variable_name)
56
- js_module = ImportJS::JSModule.new(lookup_path: nil,
57
- relative_file_path: path['path'],
58
- strip_file_extensions: [])
59
- js_module.is_destructured = true
60
- return js_module
61
- end
63
+ # @param variable_name [String]
64
+ # @return [ImportJS::JSModule?]
65
+ def resolve_named_exports(variable_name)
66
+ get('named_exports').each do |import_path, named_exports|
67
+ next unless named_exports.include?(variable_name)
68
+
69
+ js_module = ImportJS::JSModule.new(import_path: import_path)
70
+ js_module.has_named_exports = true
71
+ return js_module
62
72
  end
63
73
  nil
64
74
  end
@@ -67,26 +77,42 @@ module ImportJS
67
77
  def package_dependencies
68
78
  return [] unless File.exist?('package.json')
69
79
 
70
- package = JSON.parse(File.read('package.json'))
71
- dependencies = package['dependencies'] ?
72
- package['dependencies'].keys : []
73
- peer_dependencies = package['peerDependencies'] ?
74
- package['peerDependencies'].keys : []
75
-
76
- dependencies.concat(peer_dependencies)
80
+ keys = %w[dependencies peerDependencies]
81
+ keys << 'devDependencies' if get('import_dev_dependencies')
82
+ package_json = JSON.parse(File.read('package.json'))
83
+ keys.map do |key|
84
+ package_json[key].keys if package_json[key]
85
+ end.compact.flatten
77
86
  end
78
87
 
79
88
  private
80
89
 
90
+ # @param file [File]
81
91
  # @return [Hash]
82
- def load_config
83
- @config_time = config_file_last_modified
84
- File.exist?(CONFIG_FILE) ? JSON.parse(File.read(CONFIG_FILE)) : {}
92
+ def load_config(file)
93
+ return unless File.exist?(file)
94
+ JSON.parse(File.read(file))
95
+ end
96
+
97
+ # @param path [String]
98
+ # @return [String]
99
+ def normalize_path(path)
100
+ return './' unless path
101
+ path = path.sub(/^#{Regexp.escape(Dir.pwd)}/, '.')
102
+ path = "./#{path}" unless path.start_with?('.')
103
+ path
85
104
  end
86
105
 
87
- # @return [Time?]
88
- def config_file_last_modified
89
- File.exist?(CONFIG_FILE) ? File.mtime(CONFIG_FILE) : nil
106
+ # Checks that the current version is bigger than the `minimum_version`
107
+ # defined in config. Raises an error if it doesn't match.
108
+ def check_current_version!
109
+ minimum_version = get('minimum_version')
110
+ return if Gem::Dependency.new('', ">= #{minimum_version}")
111
+ .match?('', ImportJS::VERSION)
112
+
113
+ fail ImportJS::ClientTooOldError,
114
+ 'The .importjs.json file you are using requires version ' \
115
+ "#{get('minimum_version')}. You are using #{ImportJS::VERSION}."
90
116
  end
91
117
  end
92
118
  end
@@ -1,159 +1,159 @@
1
1
  # encoding: utf-8
2
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
- when 'fix'
26
- ImportJS::Importer.new(self).fix_imports
27
- write_file
28
- puts 'import:success'
29
- else
30
- puts "unknown command: #{command}"
3
+ # This is the implementation of the emacs integration in Import-JS.
4
+ class EmacsEditor
5
+ attr_accessor :current_word
6
+
7
+ def initialize
8
+ loop do
9
+ input = gets.chomp
10
+ command, value, path = input.split(':')
11
+
12
+ begin
13
+ @path = path
14
+ @file = File.readlines(path).map(&:chomp)
15
+ @current_word = value
16
+
17
+ case command
18
+ when 'import'
19
+ ImportJS::Importer.new(self).import
20
+ write_file
21
+ puts 'import:success'
22
+ when 'goto'
23
+ ImportJS::Importer.new(self).goto
24
+ when 'fix'
25
+ ImportJS::Importer.new(self).fix_imports
26
+ write_file
27
+ puts 'import:success'
28
+ else
29
+ puts "unknown command: #{command}"
30
+ end
31
+ rescue Exception => e
32
+ puts e.inspect
31
33
  end
32
- rescue Exception => e
33
- puts e.inspect
34
34
  end
35
35
  end
36
- end
37
36
 
38
- def write_file
39
- new_file = File.open(@path, 'w')
40
- @file.each {|line| new_file.puts(line) }
41
- new_file.close
42
- end
37
+ def write_file
38
+ new_file = File.open(@path, 'w')
39
+ @file.each { |line| new_file.puts(line) }
40
+ new_file.close
41
+ end
43
42
 
44
- # Open a file specified by a path.
45
- #
46
- # @param file_path [String]
47
- def open_file(file_path)
48
- puts "goto:success:#{File.expand_path(file_path)}"
49
- end
43
+ # Open a file specified by a path.
44
+ #
45
+ # @param file_path [String]
46
+ def open_file(file_path)
47
+ puts "goto:success:#{File.expand_path(file_path)}"
48
+ end
50
49
 
51
- # Get the path to the file currently being edited. May return `nil` if an
52
- # anonymous file is being edited.
53
- #
54
- # @return [String?]
55
- def path_to_current_file
56
- @path
57
- end
50
+ # Get the path to the file currently being edited. May return `nil` if an
51
+ # anonymous file is being edited.
52
+ #
53
+ # @return [String?]
54
+ def path_to_current_file
55
+ @path
56
+ end
58
57
 
59
- # Display a message to the user.
60
- #
61
- # @param str [String]
62
- def message(str)
63
- puts str
64
- end
58
+ # Display a message to the user.
59
+ #
60
+ # @param str [String]
61
+ def message(str)
62
+ puts str
63
+ end
65
64
 
66
- # Read the entire file into a string.
67
- #
68
- # @return [String]
69
- def current_file_content
70
- @file.join("\n")
71
- end
65
+ # Read the entire file into a string.
66
+ #
67
+ # @return [String]
68
+ def current_file_content
69
+ @file.join("\n")
70
+ end
72
71
 
73
- # Reads a line from the file.
74
- #
75
- # Lines are one-indexed, so 1 means the first line in the file.
76
- # @return [String]
77
- def read_line(line_number)
78
- @file[line_number - 1]
79
- end
72
+ # Reads a line from the file.
73
+ #
74
+ # Lines are one-indexed, so 1 means the first line in the file.
75
+ # @return [String]
76
+ def read_line(line_number)
77
+ @file[line_number - 1]
78
+ end
80
79
 
81
- # Get the cursor position.
82
- #
83
- # @return [Array(Number, Number)]
84
- def cursor
85
- return 0, 0
86
- end
80
+ # Get the cursor position.
81
+ #
82
+ # @return [Array(Number, Number)]
83
+ def cursor
84
+ [0, 0]
85
+ end
87
86
 
88
- # Place the cursor at a specified position.
89
- #
90
- # @param position_tuple [Array(Number, Number)] the row and column to place
91
- # the cursor at.
92
- def cursor=(position_tuple)
93
- end
87
+ # Place the cursor at a specified position.
88
+ #
89
+ # @param position_tuple [Array(Number, Number)] the row and column to place
90
+ # the cursor at.
91
+ def cursor=(position_tuple)
92
+ end
94
93
 
95
- # Delete a line.
96
- #
97
- # @param line_number [Number] One-indexed line number.
98
- # 1 is the first line in the file.
99
- def delete_line(line_number)
100
- @file.delete_at(line_number - 1)
101
- end
94
+ # Delete a line.
95
+ #
96
+ # @param line_number [Number] One-indexed line number.
97
+ # 1 is the first line in the file.
98
+ def delete_line(line_number)
99
+ @file.delete_at(line_number - 1)
100
+ end
102
101
 
103
- # Append a line right after the specified line.
104
- #
105
- # Lines are one-indexed, but you need to support appending to line 0 (add
106
- # content at top of file).
107
- # @param line_number [Number]
108
- def append_line(line_number, str)
109
- @file.insert(line_number, str)
110
- end
102
+ # Append a line right after the specified line.
103
+ #
104
+ # Lines are one-indexed, but you need to support appending to line 0 (add
105
+ # content at top of file).
106
+ # @param line_number [Number]
107
+ def append_line(line_number, str)
108
+ @file.insert(line_number, str)
109
+ end
111
110
 
112
- # Count the number of lines in the file.
113
- #
114
- # @return [Number] the number of lines in the file
115
- def count_lines
116
- @file.size
117
- end
111
+ # Count the number of lines in the file.
112
+ #
113
+ # @return [Number] the number of lines in the file
114
+ def count_lines
115
+ @file.size
116
+ end
118
117
 
119
- # Ask the user to select something from a list of alternatives.
120
- #
121
- # @param word [String] The word/variable to import
122
- # @param alternatives [Array<String>] A list of alternatives
123
- # @return [Number, nil] the index of the selected alternative, or nil if
124
- # nothing was selected.
125
- def ask_for_selection(word, alternatives)
126
- puts "asking for selection"
127
- puts "ImportJS: Pick JS module to import for '#{word}':"
128
- puts JSON.pretty_generate(alternatives)
129
- return
130
-
131
- # need to implement this
132
- escaped_list = [heading]
133
- escaped_list << alternatives.each_with_index.map do |alternative, i|
134
- "\"#{i + 1}: #{alternative}\""
135
- end
136
- escaped_list_string = '[' + escaped_list.join(',') + ']'
137
-
138
- selected_index = VIM.evaluate("inputlist(#{escaped_list_string})")
139
- return if selected_index < 1
140
- selected_index - 1
141
- end
118
+ # Ask the user to select something from a list of alternatives.
119
+ #
120
+ # @param word [String] The word/variable to import
121
+ # @param alternatives [Array<String>] A list of alternatives
122
+ # @return [Number, nil] the index of the selected alternative, or nil if
123
+ # nothing was selected.
124
+ def ask_for_selection(word, alternatives)
125
+ puts 'asking for selection'
126
+ puts "ImportJS: Pick JS module to import for '#{word}':"
127
+ puts JSON.pretty_generate(alternatives)
128
+ return
129
+
130
+ # need to implement this
131
+ escaped_list = [heading]
132
+ escaped_list << alternatives.each_with_index.map do |alternative, i|
133
+ "\"#{i + 1}: #{alternative}\""
134
+ end
135
+ escaped_list_string = '[' + escaped_list.join(',') + ']'
142
136
 
143
- # Get the preferred max length of a line
144
- # @return [Number?]
145
- def max_line_length
146
- 80
147
- end
137
+ selected_index = VIM.evaluate("inputlist(#{escaped_list_string})")
138
+ return if selected_index < 1
139
+ selected_index - 1
140
+ end
148
141
 
149
- # @return [String] shiftwidth number of spaces if expandtab is not set,
150
- # otherwise `\t`
151
- def tab
152
- return ' ' * shift_width || 2
153
- end
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
154
153
 
155
- # @return [Number?]
156
- def shift_width
157
- 2
154
+ # @return [Number?]
155
+ def shift_width
156
+ 2
157
+ end
158
158
  end
159
159
  end