|
3 | 3 | require "json"
|
4 | 4 |
|
5 | 5 | class Importmap::Npm
|
| 6 | + PIN_REGEX = /^pin ["']([^["']]*)["'].*/ |
| 7 | + |
6 | 8 | Error = Class.new(StandardError)
|
7 | 9 | HTTPError = Class.new(Error)
|
8 | 10 |
|
9 | 11 | singleton_class.attr_accessor :base_uri
|
10 | 12 | self.base_uri = URI("https://registry.npmjs.org")
|
11 | 13 |
|
12 |
| - def initialize(importmap_path = "config/importmap.rb") |
| 14 | + def initialize(importmap_path = "config/importmap.rb", vendor_path: "vendor/javascript") |
13 | 15 | @importmap_path = Pathname.new(importmap_path)
|
| 16 | + @vendor_path = Pathname.new(vendor_path) |
14 | 17 | end
|
15 | 18 |
|
16 | 19 | def outdated_packages
|
@@ -48,16 +51,20 @@ def packages_with_versions
|
48 | 51 | # We cannot use the name after "pin" because some dependencies are loaded from inside packages
|
49 | 52 | # Eg. pin "buffer", to: "https://ga.jspm.io/npm:@jspm/[email protected]/nodelibs/browser/buffer.js"
|
50 | 53 |
|
51 |
| - importmap.scan(/^pin .*(?<=npm:|npm\/|skypack\.dev\/|unpkg\.com\/)(.*)(?=@\d+\.\d+\.\d+)@(\d+\.\d+\.\d+(?:[^\/\s["']]*)).*$/) | |
52 |
| - importmap.scan(/^pin ["']([^["']]*)["'].* #.*@(\d+\.\d+\.\d+(?:[^\s]*)).*$/) |
| 54 | + with_versions = importmap.scan(/^pin .*(?<=npm:|npm\/|skypack\.dev\/|unpkg\.com\/)(.*)(?=@\d+\.\d+\.\d+)@(\d+\.\d+\.\d+(?:[^\/\s["']]*)).*$/) | |
| 55 | + importmap.scan(/#{PIN_REGEX} #.*@(\d+\.\d+\.\d+(?:[^\s]*)).*$/) |
| 56 | + |
| 57 | + vendored_packages_without_version(with_versions).each do |package, path| |
| 58 | + $stdout.puts "Ignoring #{package} (#{path}) since no version is specified in the importmap" |
| 59 | + end |
| 60 | + |
| 61 | + with_versions |
53 | 62 | end
|
54 | 63 |
|
55 | 64 | private
|
56 | 65 | OutdatedPackage = Struct.new(:name, :current_version, :latest_version, :error, keyword_init: true)
|
57 | 66 | VulnerablePackage = Struct.new(:name, :severity, :vulnerable_versions, :vulnerability, keyword_init: true)
|
58 | 67 |
|
59 |
| - |
60 |
| - |
61 | 68 | def importmap
|
62 | 69 | @importmap ||= File.read(@importmap_path)
|
63 | 70 | end
|
@@ -130,4 +137,19 @@ def post_json(uri, body)
|
130 | 137 | rescue => error
|
131 | 138 | raise HTTPError, "Unexpected transport error (#{error.class}: #{error.message})"
|
132 | 139 | end
|
| 140 | + |
| 141 | + def vendored_packages_without_version(packages_with_versions) |
| 142 | + importmap |
| 143 | + .lines |
| 144 | + .filter_map do |line| |
| 145 | + next line.match(/#{PIN_REGEX}to: ["']([^["']]*)["'].*/).captures if line.include?("to:") |
| 146 | + match = line.match(PIN_REGEX) |
| 147 | + [match.captures.first, "#{match.captures.first}.js"] if match |
| 148 | + end |
| 149 | + .filter_map do |package, filename| |
| 150 | + next if packages_with_versions.map(&:first).include?(package) |
| 151 | + path = File.join(@vendor_path, filename) |
| 152 | + [package, path] if File.exist?(path) |
| 153 | + end |
| 154 | + end |
133 | 155 | end
|
0 commit comments