Skip to content

Commit a0d03d2

Browse files
committed
Rework importmap
Skypack seems abandoned: - skypackjs/skypack-cdn#365 - skypackjs/skypack-cdn#362 importmap-rails switched logic to always download: rails/importmap-rails#217 But it doesn't work for complex bigger packages. There's a WIP PR to address this: rails/importmap-rails#235 So I decided to use the new rails-importmap approach where I can, and switch to jsdelivr where I have to. I've pinned to major versions and jsdelivr should take care of everything else. I've also updated the rake task to check for major version updates.
1 parent 63dde91 commit a0d03d2

File tree

6 files changed

+421
-62
lines changed

6 files changed

+421
-62
lines changed

Diff for: Gemfile.lock

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ GEM
101101
rack
102102
ast (2.4.2)
103103
aws-eventstream (1.3.0)
104-
aws-partitions (1.903.0)
104+
aws-partitions (1.904.0)
105105
aws-sdk-core (3.191.5)
106106
aws-eventstream (~> 1, >= 1.3.0)
107107
aws-partitions (~> 1, >= 1.651.0)

Diff for: config/importmap.rb

+8-6
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
pin "@hotwired/stimulus", to: "stimulus.min.js"
66
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
77

8-
# use rails importmap:update to update these to the latest version
9-
pin "stimulus-autocomplete", to: "https://cdn.skypack.dev/pin/[email protected]/mode=imports/optimized/stimulus-autocomplete.js" # source: https://cdn.skypack.dev/stimulus-autocomplete
10-
pin "el-transition", to: "https://cdn.skypack.dev/pin/[email protected]/mode=imports/optimized/el-transition.js" # source: https://cdn.skypack.dev/el-transition
11-
pin "highcharts", to: "https://cdn.skypack.dev/pin/[email protected]/mode=imports/unoptimized/es-modules/masters/highcharts.src.js" # source: https://cdn.skypack.dev/highcharts/es-modules/masters/highcharts.src.js
12-
pin "highcharts-annotations", to: "https://cdn.skypack.dev/pin/[email protected]/mode=imports/unoptimized/es-modules/masters/modules/annotations.src.js" # source: https://cdn.skypack.dev/highcharts/es-modules/masters/modules/annotations.src.js
13-
pin "highlight.js", to: "https://cdn.skypack.dev/pin/[email protected]/mode=imports/optimized/highlightjs.js" # source: https://cdn.skypack.dev/highlight.js
8+
# use bin/importmap update to update these to the latest version
9+
pin "stimulus-autocomplete" # @3.1.0
10+
pin "el-transition" # @0.0.7
11+
12+
# use rails importmap:check to check for major version changes
13+
pin "highcharts", to: "https://cdn.jsdelivr.net/npm/highcharts@11/es-modules/masters/highcharts.src.js"
14+
pin "highcharts-annotations", to: "https://cdn.jsdelivr.net/npm/highcharts@11/es-modules/masters/modules/annotations.src.js"
15+
pin "highlight.js", to: "https://cdn.jsdelivr.net/npm/highlight.js@11/+esm"
1416

1517
pin_all_from "app/javascript/channels", under: "channels"
1618
pin_all_from "app/javascript/controllers", under: "controllers"

Diff for: lib/tasks/check_importmap.rake

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
require "concurrent"
2+
3+
class ImportMapChecker
4+
attr_reader :file, :content, :mutex
5+
6+
def initialize
7+
@file = Rails.root.join("config/importmap.rb")
8+
@content = File.read(file)
9+
@mutex = Mutex.new
10+
end
11+
12+
def check
13+
futures.each(&:value)
14+
end
15+
16+
private
17+
18+
def futures
19+
@futures ||= content.split("\n").filter_map { |line| create_future(line) }
20+
end
21+
22+
def create_future(line)
23+
return unless line.include?("jsdelivr")
24+
25+
Concurrent::Future.execute do
26+
current_url = line[/to: "(.*)"/, 1]
27+
non_versioned_url = current_url.sub(/@[\d]+\//, "/")
28+
current_version = URI(current_url)
29+
latest_version = URI(non_versioned_url)
30+
31+
current = Net::HTTP.get_response(URI(current_version))
32+
if current.is_a?(Net::HTTPSuccess)
33+
latest = Net::HTTP.get_response(URI(latest_version))
34+
if latest.is_a?(Net::HTTPSuccess)
35+
puts "There is a new major version of #{current_url} available" if current.body != latest.body
36+
else
37+
puts "Could not fetch #{latest_version}"
38+
end
39+
else
40+
puts "Could not fetch #{current_version}"
41+
end
42+
end
43+
end
44+
end
45+
46+
namespace :importmap do
47+
task check: :environment do
48+
ImportMapChecker.new.check
49+
end
50+
end

Diff for: lib/tasks/update_importmap.rake

-55
This file was deleted.

Diff for: vendor/javascript/el-transition.js

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
export async function enter(element, transitionName = null) {
2+
element.classList.remove('hidden')
3+
await transition('enter', element, transitionName)
4+
}
5+
6+
export async function leave(element, transitionName = null) {
7+
await transition('leave', element, transitionName)
8+
element.classList.add('hidden')
9+
}
10+
11+
export async function toggle(element, transitionName = null) {
12+
if (element.classList.contains('hidden')) {
13+
await enter(element, transitionName)
14+
} else {
15+
await leave(element, transitionName)
16+
}
17+
}
18+
19+
async function transition(direction, element, animation) {
20+
const dataset = element.dataset
21+
const animationClass = animation ? `${animation}-${direction}` : direction
22+
let transition = `transition${direction.charAt(0).toUpperCase() + direction.slice(1)}`
23+
const genesis = dataset[transition] ? dataset[transition].split(" ") : [animationClass]
24+
const start = dataset[`${transition}Start`] ? dataset[`${transition}Start`].split(" ") : [`${animationClass}-start`]
25+
const end = dataset[`${transition}End`] ? dataset[`${transition}End`].split(" ") : [`${animationClass}-end`]
26+
27+
addClasses(element, genesis)
28+
addClasses(element, start)
29+
await nextFrame()
30+
removeClasses(element, start)
31+
addClasses(element, end);
32+
await afterTransition(element)
33+
removeClasses(element, end)
34+
removeClasses(element, genesis)
35+
}
36+
37+
function addClasses(element, classes) {
38+
element.classList.add(...classes)
39+
}
40+
41+
function removeClasses(element, classes) {
42+
element.classList.remove(...classes)
43+
}
44+
45+
function nextFrame() {
46+
return new Promise(resolve => {
47+
requestAnimationFrame(() => {
48+
requestAnimationFrame(resolve)
49+
});
50+
});
51+
}
52+
53+
function afterTransition(element) {
54+
return new Promise(resolve => {
55+
// safari return string with comma separate values
56+
const computedDuration = getComputedStyle(element).transitionDuration.split(",")[0]
57+
const duration = Number(computedDuration.replace('s', '')) * 1000;
58+
setTimeout(() => {
59+
resolve()
60+
}, duration)
61+
});
62+
}

0 commit comments

Comments
 (0)