Skip to content

Commit a04dd30

Browse files
committed
Handle package names with nested paths in import maps
Packages with nested paths (e.g., "photoswipe/lightbox" or "@github/webauthn-json/browser-ponyfill") were not being correctly identified, leading to issues when checking for outdated versions. This update modifies the package name extraction logic to correctly handle such cases. Fixes #321,
1 parent 9b0a9e0 commit a04dd30

8 files changed

Lines changed: 72 additions & 2 deletions

.github/prompts/fix-issue.prompt.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
mode: agent
2+
agent: agent
33
description: 'Fix an issue in the importmap-rails gem by following a systematic process.'
44
---
55
# GitHub Issue Fixer Prompt

.github/prompts/generate-commit-message.prompt.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
mode: agent
2+
agent: agent
33
description: 'Generate clear, descriptive commit messages for importmap-rails changes'
44
---
55
# Commit Message Generator

lib/importmap/npm.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ def packages_with_versions
5454
with_versions = importmap.scan(/^pin .*(?<=npm:|npm\/|skypack\.dev\/|unpkg\.com\/)([^@\/]+)@(\d+\.\d+\.\d+(?:[^\/\s"']*))/) |
5555
importmap.scan(/#{PIN_REGEX} #.*@(\d+\.\d+\.\d+(?:[^\s]*)).*$/)
5656

57+
with_versions.map! do |package, version|
58+
[extract_base_package_name(package), version]
59+
end.uniq!
60+
5761
vendored_packages_without_version(with_versions).each do |package, path|
5862
$stdout.puts "Ignoring #{package} (#{path}) since no version is specified in the importmap"
5963
end
@@ -138,6 +142,17 @@ def post_json(uri, body)
138142
raise HTTPError, "Unexpected transport error (#{error.class}: #{error.message})"
139143
end
140144

145+
def extract_base_package_name(package)
146+
if package.start_with?("@")
147+
# Scoped packages can have nested paths, e.g. @scope/package/subpath
148+
parts = package.split("/", 3)
149+
parts.size > 2 ? parts.first(2).join("/") : package
150+
else
151+
# Non-scoped packages - just take the first part
152+
package.split("/").first
153+
end
154+
end
155+
141156
def vendored_packages_without_version(packages_with_versions)
142157
versioned_packages = packages_with_versions.map(&:first).to_set
143158

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pin "photoswipe/lightbox", to: "https://ga.jspm.io/npm:photoswipe@5.4.4/dist/photoswipe-lightbox.esm.js"
2+
pin "photoswipe", to: "https://ga.jspm.io/npm:photoswipe@5.4.4/dist/photoswipe.esm.js"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pin "photoswipe/lightbox", to: "https://ga.jspm.io/npm:photoswipe@5.4.4/dist/photoswipe-lightbox.esm.js" # @5.4.4
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pin "@github/webauthn-json", to: "https://ga.jspm.io/npm:@github/webauthn-json@2.1.1/dist/esm/webauthn-json.js" # @2.1.1
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pin "@github/webauthn-json/browser-ponyfill", to: "https://ga.jspm.io/npm:@github/webauthn-json@2.1.1/dist/esm/webauthn-json.browser-ponyfill.js" # @2.1.1

test/npm_test.rb

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,56 @@ class Importmap::NpmTest < ActiveSupport::TestCase
4646
end
4747
end
4848

49+
test "extracts package name and version from nested package path" do
50+
npm = Importmap::Npm.new(file_fixture("nested_package_path_import_map.rb"))
51+
packages = npm.packages_with_versions
52+
53+
assert_equal(1, packages.size)
54+
assert_equal('photoswipe', packages[0][0])
55+
assert_equal('5.4.4', packages[0][1])
56+
end
57+
58+
test "extracts only base package name from nested package path with version comment" do
59+
npm = Importmap::Npm.new(file_fixture("nested_package_with_comment_import_map.rb"))
60+
packages = npm.packages_with_versions
61+
62+
assert_equal(1, packages.size)
63+
assert_equal('photoswipe', packages[0][0])
64+
assert_equal('5.4.4', packages[0][1])
65+
end
66+
67+
test "handles scoped package with nested path" do
68+
npm = Importmap::Npm.new(file_fixture("scoped_package_with_nested_path_import_map.rb"))
69+
packages = npm.packages_with_versions
70+
71+
assert_equal(1, packages.size)
72+
assert_equal('@github/webauthn-json', packages[0][0])
73+
assert_equal('2.1.1', packages[0][1])
74+
end
75+
76+
test "handles regular scoped package without nested path" do
77+
npm = Importmap::Npm.new(file_fixture("scoped_package_import_map.rb"))
78+
packages = npm.packages_with_versions
79+
80+
assert_equal(1, packages.size)
81+
assert_equal('@github/webauthn-json', packages[0][0])
82+
assert_equal('2.1.1', packages[0][1])
83+
end
84+
85+
test "successful outdated packages with nested package path using mock" do
86+
npm = Importmap::Npm.new(file_fixture("nested_package_path_import_map.rb"))
87+
response = { "dist-tags" => { "latest" => '5.5.0' } }.to_json
88+
89+
npm.stub(:get_json, response) do
90+
outdated_packages = npm.outdated_packages
91+
92+
assert_equal(1, outdated_packages.size)
93+
assert_equal('photoswipe', outdated_packages[0].name)
94+
assert_equal('5.4.4', outdated_packages[0].current_version)
95+
assert_equal('5.5.0', outdated_packages[0].latest_version)
96+
end
97+
end
98+
4999
test "warns (and ignores) vendored packages without version" do
50100
Dir.mktmpdir do |vendor_path|
51101
foo_path = create_vendored_file(vendor_path, "foo.js")

0 commit comments

Comments
 (0)