importmap-rails 2.0.1 → 2.0.2

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
  SHA256:
3
- metadata.gz: f1409421a79c426cb82404b0c910dedb0c5ec2dc733304e5f907f92067cfb208
4
- data.tar.gz: 138353eac33ffcbbe8a80ce4a8202485792e4609122409478bc5dc9fa324650d
3
+ metadata.gz: 63eb750638abbf09f2148c2b345afe06e994fbedc3ead36c7d05666d8da7c6ad
4
+ data.tar.gz: 6247744c8affa11695554918798cfe69252b2d80491f6449ba97d9eed9eb19ef
5
5
  SHA512:
6
- metadata.gz: 3f248fc4722407b75d81d533c52b368a8a12fceaf10ba9cd7d103c10a103d0722013910eaecdc824cd5076a0fd073fefa6c08020bd97a5a5d9948fb696091416
7
- data.tar.gz: 56ca2998ed2b6e73b50d691da2894593dbf31f2092cc16db5c26cb7aea46ebb71995660ee75945daaf5a32e355fe953d3d141b4612ab87e56744ce70e4cbcc65
6
+ metadata.gz: 448fc351ee3e3a2e7e1b9c5b3b7c3136f2b953dd01777885cc5fcd88b3d0c34a5f14d9c11d5f8737e7f770967130b1050657ae9d4a9ade56a57ffaf1cbd0bede
7
+ data.tar.gz: c01dceda01dd2493cb28e1c3f4fc7e1b839683f0beb8f62c4130ad375acf79809022106451f4164ae48709b77290847dd5a5ea1d3cbbc636b0f9133164de2bc6
data/README.md CHANGED
@@ -141,6 +141,25 @@ pin "md5", preload: false # file lives in vendor/javascript/md5.js
141
141
  ...
142
142
  ```
143
143
 
144
+ You can also specify which entry points to preload a particular dependency in by providing `preload:` a string or array of strings.
145
+
146
+ Example:
147
+
148
+ ```ruby
149
+ # config/importmap.rb
150
+ pin "@github/hotkey", to: "@github--hotkey.js", preload: 'application'
151
+ pin "md5", preload: ['application', 'alternate']
152
+
153
+ # app/views/layouts/application.html.erb
154
+ <%= javascript_importmap_tags 'alternate' %>
155
+
156
+ # will include the following link before the importmap is setup:
157
+ <link rel="modulepreload" href="/assets/javascript/md5.js">
158
+ ...
159
+ ```
160
+
161
+
162
+
144
163
  ## Composing import maps
145
164
 
146
165
  By default, Rails loads import map definition from the application's `config/importmap.rb` to the `Importmap::Map` object available at `Rails.application.importmap`.
@@ -207,7 +226,7 @@ Import your module on the specific page. Note: you'll likely want to use a `cont
207
226
 
208
227
  ## Include a digest of the import map in your ETag
209
228
 
210
- If you're using [ETags](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) generated by Rails helpers like `stale?` or `fresh_when`, you need to include the digest of the import map into this calculation. Otherwise your application will return 302 cache responses even when your JavaScript assets have changed. You can avoid this with something like:
229
+ If you're using [ETags](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) generated by Rails helpers like `stale?` or `fresh_when`, you need to include the digest of the import map into this calculation. Otherwise your application will return [304](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304) cache responses even when your JavaScript assets have changed. You can avoid this with something like:
211
230
 
212
231
  ```ruby
213
232
  class ApplicationController < ActionController::Base
@@ -242,6 +261,15 @@ Importmap for Rails provides two commands to check your pinned packages:
242
261
  - `./bin/importmap outdated` checks the NPM registry for new versions
243
262
  - `./bin/importmap audit` checks the NPM registry for known security issues
244
263
 
264
+ ## Supporting legacy browsers such as Safari on iOS 15
265
+
266
+ If you want to support [legacy browsers that do not support import maps](https://caniuse.com/import-maps) such as [iOS 15.8.1 released on 22 Jan 2024](https://support.apple.com/en-us/HT201222), insert [`es-module-shims`](https://github.com/guybedford/es-module-shims) before `javascript_importmap_tags` as below.
267
+
268
+ ```erb
269
+ <script async src="https://ga.jspm.io/npm:es-module-shims@1.8.2/dist/es-module-shims.js" data-turbo-track="reload"></script>
270
+ <%= javascript_importmap_tags %>
271
+ ```
272
+
245
273
  ## License
246
274
 
247
275
  Importmap for Rails is released under the [MIT License](https://opensource.org/licenses/MIT).
@@ -3,7 +3,7 @@ module Importmap::ImportmapTagsHelper
3
3
  def javascript_importmap_tags(entry_point = "application", importmap: Rails.application.importmap)
4
4
  safe_join [
5
5
  javascript_inline_importmap_tag(importmap.to_json(resolver: self)),
6
- javascript_importmap_module_preload_tags(importmap),
6
+ javascript_importmap_module_preload_tags(importmap, entry_point:),
7
7
  javascript_import_module_tag(entry_point)
8
8
  ], "\n"
9
9
  end
@@ -24,8 +24,8 @@ module Importmap::ImportmapTagsHelper
24
24
  # Link tags for preloading all modules marked as preload: true in the `importmap`
25
25
  # (defaults to Rails.application.importmap), such that they'll be fetched
26
26
  # in advance by browsers supporting this link type (https://caniuse.com/?search=modulepreload).
27
- def javascript_importmap_module_preload_tags(importmap = Rails.application.importmap)
28
- javascript_module_preload_tag(*importmap.preloaded_module_paths(resolver: self))
27
+ def javascript_importmap_module_preload_tags(importmap = Rails.application.importmap, entry_point: "application")
28
+ javascript_module_preload_tag(*importmap.preloaded_module_paths(resolver: self, entry_point:, cache_key: entry_point))
29
29
  end
30
30
 
31
31
  # Link tag(s) for preloading the JavaScript module residing in `*paths`. Will return one link tag per path element.
@@ -92,7 +92,7 @@ class Importmap::Commands < Thor
92
92
  desc "update", "Update outdated package pins"
93
93
  def update
94
94
  if (outdated_packages = npm.outdated_packages).any?
95
- pin outdated_packages.map(&:name)
95
+ pin(*outdated_packages.map(&:name))
96
96
  else
97
97
  puts "No outdated packages found"
98
98
  end
data/lib/importmap/map.rb CHANGED
@@ -40,9 +40,9 @@ class Importmap::Map
40
40
  # resolver that has been configured for the `asset_host` you want these resolved paths to use. In case you need to
41
41
  # resolve for different asset hosts, you can pass in a custom `cache_key` to vary the cache used by this method for
42
42
  # the different cases.
43
- def preloaded_module_paths(resolver:, cache_key: :preloaded_module_paths)
43
+ def preloaded_module_paths(resolver:, entry_point: "application", cache_key: :preloaded_module_paths)
44
44
  cache_as(cache_key) do
45
- resolve_asset_paths(expanded_preloading_packages_and_directories, resolver: resolver).values
45
+ resolve_asset_paths(expanded_preloading_packages_and_directories(entry_point:), resolver:).values
46
46
  end
47
47
  end
48
48
 
@@ -118,8 +118,8 @@ class Importmap::Map
118
118
  end.compact
119
119
  end
120
120
 
121
- def expanded_preloading_packages_and_directories
122
- expanded_packages_and_directories.select { |name, mapping| mapping.preload }
121
+ def expanded_preloading_packages_and_directories(entry_point:)
122
+ expanded_packages_and_directories.select { |name, mapping| mapping.preload.in?([true, false]) ? mapping.preload : (Array(mapping.preload) & Array(entry_point)).any? }
123
123
  end
124
124
 
125
125
  def expanded_packages_and_directories
@@ -141,7 +141,17 @@ class Importmap::Map
141
141
  end
142
142
 
143
143
  def module_name_from(filename, mapping)
144
- [ mapping.under, filename.to_s.remove(filename.extname).remove(/\/?index$/).presence ].compact.join("/")
144
+ # Regex explanation:
145
+ # (?:\/|^) # Matches either / OR the start of the string
146
+ # index # Matches the word index
147
+ # $ # Matches the end of the string
148
+ #
149
+ # Sample matches
150
+ # index
151
+ # folder/index
152
+ index_regex = /(?:\/|^)index$/
153
+
154
+ [ mapping.under, filename.to_s.remove(filename.extname).remove(index_regex).presence ].compact.join("/")
145
155
  end
146
156
 
147
157
  def module_path_from(filename, mapping)
data/lib/importmap/npm.rb CHANGED
@@ -86,7 +86,7 @@ class Importmap::Npm
86
86
  end
87
87
 
88
88
  def find_latest_version(response)
89
- latest_version = response.dig('dist-tags', 'latest')
89
+ latest_version = response.is_a?(String) ? response : response.dig('dist-tags', 'latest')
90
90
  return latest_version if latest_version
91
91
 
92
92
  return unless response['versions']
@@ -19,10 +19,10 @@ class Importmap::Packager
19
19
 
20
20
  def import(*packages, env: "production", from: "jspm")
21
21
  response = post_json({
22
- "install" => Array(packages),
22
+ "install" => Array(packages),
23
23
  "flattenScope" => true,
24
24
  "env" => [ "browser", "module", env ],
25
- "provider" => from.to_s,
25
+ "provider" => normalize_provider(from)
26
26
  })
27
27
 
28
28
  case response.code
@@ -69,6 +69,10 @@ class Importmap::Packager
69
69
  raise HTTPError, "Unexpected transport error (#{error.class}: #{error.message})"
70
70
  end
71
71
 
72
+ def normalize_provider(name)
73
+ name.to_s == "jspm" ? "jspm.io" : name.to_s
74
+ end
75
+
72
76
  def extract_parsed_imports(response)
73
77
  JSON.parse(response.body).dig("map", "imports")
74
78
  end
@@ -80,7 +84,7 @@ class Importmap::Packager
80
84
  raise HTTPError, "Unexpected response code (#{response.code})"
81
85
  end
82
86
  end
83
-
87
+
84
88
  def parse_service_error(response)
85
89
  JSON.parse(response.body.to_s)["error"]
86
90
  rescue JSON::ParserError
@@ -113,14 +117,16 @@ class Importmap::Packager
113
117
  response = Net::HTTP.get_response(URI(url))
114
118
 
115
119
  if response.code == "200"
116
- save_vendored_package(package, response.body)
120
+ save_vendored_package(package, url, response.body)
117
121
  else
118
122
  handle_failure_response(response)
119
123
  end
120
124
  end
121
125
 
122
- def save_vendored_package(package, source)
126
+ def save_vendored_package(package, url, source)
123
127
  File.open(vendored_package_path(package), "w+") do |vendored_package|
128
+ vendored_package.write "// #{package}#{extract_package_version_from(url)} downloaded from #{url}\n\n"
129
+
124
130
  vendored_package.write remove_sourcemap_comment_from(source).force_encoding("UTF-8")
125
131
  end
126
132
  end
@@ -1,3 +1,3 @@
1
1
  module Importmap
2
- VERSION = "2.0.1"
2
+ VERSION = "2.0.2"
3
3
  end
@@ -1,6 +1,9 @@
1
1
  namespace :importmap do
2
2
  desc "Setup Importmap for the app"
3
3
  task :install do
4
- system RbConfig.ruby, "./bin/rails", "app:template", "LOCATION=#{File.expand_path("../install/install.rb", __dir__)}"
4
+ previous_location = ENV["LOCATION"]
5
+ ENV["LOCATION"] = File.expand_path("../install/install.rb", __dir__)
6
+ Rake::Task["app:template"].invoke
7
+ ENV["LOCATION"] = previous_location
5
8
  end
6
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: importmap-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-03 00:00:00.000000000 Z
11
+ date: 2024-10-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -95,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  requirements: []
98
- rubygems_version: 3.4.14
98
+ rubygems_version: 3.5.16
99
99
  signing_key:
100
100
  specification_version: 4
101
101
  summary: Use ESM with importmap to manage modern JavaScript in Rails without transpiling