Skip to content

Commit a53db19

Browse files
committed
Initial commit
0 parents  commit a53db19

File tree

3 files changed

+99
-0
lines changed

3 files changed

+99
-0
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# js-import-resolve (Sublime plugin)
2+
3+
Shows clickable links when hovering js imports (supports `require()` and `import ... from X`).
4+
5+
Works for npm modules and local files. Screenshot:
6+
7+
![](screenshot.png)

js_import_resolve.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import sublime
2+
import sublime_plugin
3+
import json
4+
import os
5+
import re
6+
7+
#
8+
# Utils
9+
#
10+
11+
def extract_import_values(line):
12+
commonjs = re.finditer(r'\brequire\s*\(["\']([^"\']+)', line)
13+
commonjs_values = []
14+
for group in commonjs:
15+
commonjs_values.append(group.group(1))
16+
if len(commonjs_values) > 0:
17+
return commonjs_values
18+
es6import = re.search(r'import.*\sfrom\s+["\']([^"\']+)', line)
19+
if es6import:
20+
return [es6import.group(1)]
21+
return []
22+
23+
assert extract_import_values("const { createCanvas } = require('canvas');") == ['canvas']
24+
assert extract_import_values("const { createCanvas } = require ('canvas');") == ['canvas']
25+
assert extract_import_values("const { createCanvas } = require(\"canvas\");") == ['canvas']
26+
assert extract_import_values("const { createCanvas } = require('asd-foo');") == ['asd-foo']
27+
assert extract_import_values("const { createCanvas } = require('./asd.js');") == ['./asd.js']
28+
assert extract_import_values("const { createCanvas } = require('../asd.js');") == ['../asd.js']
29+
assert extract_import_values("const { createCanvas } = require('./nested/asd.js');") == ['./nested/asd.js']
30+
31+
assert extract_import_values("const foo = require('asd'); const yay = require('hmm');") == ['asd', 'hmm']
32+
33+
assert extract_import_values("import { createCanvas } from 'canvas';") == ['canvas']
34+
assert extract_import_values("import { createCanvas } from 'canvas';") == ['canvas']
35+
assert extract_import_values("import { createCanvas } from \"canvas\";") == ['canvas']
36+
assert extract_import_values("import { createCanvas } from 'asd-foo';") == ['asd-foo']
37+
assert extract_import_values("import { createCanvas } from './asd.js';") == ['./asd.js']
38+
assert extract_import_values("import { createCanvas } from '../asd.js';") == ['../asd.js']
39+
assert extract_import_values("import { createCanvas } from './nested/asd.js';") == ['./nested/asd.js']
40+
41+
def clean_path(path):
42+
path = re.sub(r'\/\.\/', '/', path)
43+
path = re.sub(r'\/[^\/]+\/\.\.\/', '/', path)
44+
return path
45+
46+
assert clean_path('/foo/./bar') == '/foo/bar'
47+
assert clean_path('/foo/../bar') == '/bar'
48+
49+
def resolve_js_file_path(path):
50+
variations = [path]
51+
if not path.endswith('.js'):
52+
variations.append(path + '.js')
53+
if not path.endswith('.json'):
54+
variations.append(path + '.json')
55+
for variation in variations:
56+
if os.path.isfile(variation):
57+
return variation
58+
return None
59+
60+
#
61+
# Main
62+
#
63+
64+
class HoverListener(sublime_plugin.EventListener):
65+
def on_hover(self, view, point, hover_zone):
66+
line = view.substr(view.line(point))
67+
values = extract_import_values(line)
68+
if len(values) > 0:
69+
paths = []
70+
for value in values:
71+
if value[0] == '.':
72+
file_path = resolve_js_file_path(clean_path(os.path.join(os.path.dirname(view.file_name()), value)))
73+
if file_path:
74+
paths.append(file_path)
75+
break
76+
else:
77+
dirname = os.path.dirname(view.file_name())
78+
counter = 0
79+
while dirname != '/' and counter < 20:
80+
if os.path.isdir(os.path.join(dirname, 'node_modules')):
81+
module_path = os.path.join(dirname, 'node_modules', value)
82+
if os.path.isdir(module_path):
83+
with open(os.path.join(module_path, 'package.json'), 'r') as file:
84+
package_information = json.loads(file.read())
85+
if package_information['main']:
86+
file_path = resolve_js_file_path(clean_path(os.path.join(module_path, package_information['main'])))
87+
paths.append(file_path)
88+
break
89+
counter += 1
90+
dirname = os.path.dirname(dirname)
91+
html = '<br>'.join(map(lambda path: '<a href="' + path + '">' + path + '</a>', paths))
92+
view.show_popup(html, sublime.HIDE_ON_MOUSE_MOVE_AWAY, point, 1000, 1000, lambda href: view.window().open_file(href))

screenshot.png

41.8 KB
Loading

0 commit comments

Comments
 (0)