importmap-rails 0.7.1 → 0.7.5

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: 6f178f76220fe01a13e2d79033cabc5261f790102abdd8d0209741cb8c7a6b17
4
- data.tar.gz: 450c1fd3351c4caf38a88e58ad9c3d9cd25b919c3cafab86e5acbcf977ab6e38
3
+ metadata.gz: 38c3083184e97d6df1566c84b82011280e8ebc5b68d59daeac2eff60b8264bf6
4
+ data.tar.gz: 705e1989000dbae9d04e18555de12ad968f3fa557a65de7ca5eb87f6adbdf335
5
5
  SHA512:
6
- metadata.gz: e119612311447feb13be274fb897a44f1a25d08d12287a66ecd8661638e4884c4f79b6d275e630c0e1661f70a5b9753d57c1e33d8dcbc605a5470fb2add8bc0b
7
- data.tar.gz: b647688c8a0f634d97d9a3204673cb43eab80086ab3313debce1faee335d0f1abc0e22aada01552fc6f756a9a6233bd64c7dd949933b14fe5beaaa9312679fd4
6
+ metadata.gz: 9a7181a347eb789eb72d3f14d76a11004d1683c5e9dc7e8ddb9810a37445ad66f392105874c4a663ac939df55052f9184e33200d7ec27b458bf176de3ad225e5
7
+ data.tar.gz: 994fefc659e8b26a50ac3382f16c14436f2aa7343d4d9c6a7679b0044dafa5a3dac082a2818a4c9ee41ed6922b52a4d9e4668771d605763e34f92d8b6e687230
data/README.md CHANGED
@@ -48,7 +48,7 @@ Pinning "scheduler" to https://ga.jspm.io/npm:scheduler@0.20.2/index.js
48
48
 
49
49
  {
50
50
  "imports": {
51
- "application": "/application.js",
51
+ "application": "/assets/application-37f365cbecf1fa2810a8303f4b6571676fa1f9c56c248528bc14ddb857531b95.js",
52
52
  "react": "https://ga.jspm.io/npm:react@17.0.2/index.js",
53
53
  "react-dom": "https://ga.jspm.io/npm:react-dom@17.0.2/index.js",
54
54
  "object-assign": "https://ga.jspm.io/npm:object-assign@4.1.1/index.js",
@@ -169,9 +169,9 @@ pin_all_from File.expand_path("../app/assets/javascripts", __dir__)
169
169
  ```
170
170
 
171
171
 
172
- ## Include a digest of the import map in your etag
172
+ ## Include a digest of the import map in your ETag
173
173
 
174
- If you're using etags 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:
174
+ 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:
175
175
 
176
176
  ```ruby
177
177
  class ApplicationController < ActionController::Base
@@ -182,7 +182,7 @@ end
182
182
 
183
183
  ## Sweeping the cache in development and test
184
184
 
185
- Generating the import map json and modulepreloads may require resolving hundreds of assets. This can take a while, so these operations are cached, but in development and test, we watch for changes to both `config/importmap.rb` and files in `app/javascript` to clear this cache. This feature can be controlled in an environment configuration file via the boolean `config.importmap.sweep_cache`. If you're pinning local files from outside of `app/javascript`, you'll need to restart your development server upon changes.
185
+ Generating the import map json and modulepreloads may require resolving hundreds of assets. This can take a while, so these operations are cached, but in development and test, we watch for changes to both `config/importmap.rb` and files in `app/javascript` to clear this cache. This feature can be controlled in an environment configuration file via the boolean `config.importmap.sweep_cache`. If you're pinning local files from outside of `app/javascript`, you'll need to restart your development server upon changes to those external files.
186
186
 
187
187
 
188
188
  ## Expected errors from using the es-module-shim
@@ -192,12 +192,12 @@ While import maps are native in Chrome and Edge, they need a shim in other brows
192
192
 
193
193
  ## Turning off the shim
194
194
 
195
- Under certain circumstances, like running system tests using chromedriver under CI (which may be resource constrained and trigger errors in certain cases), you may want to explicitly turn off including the shim. If can do this by calling the bulk tag helper with `javascript_importmap_tags("application", shim: false)`. Thus you can pass in something like `shim: !ENV["CI"]`. If you want, and are sure you're not doing any full-page caching, you can also connect this directive to a user agent check (using a gem like `useragent`) to check whether the browser is chrome/edge 89+. But you really shouldn't have to, as the shim is designed to gracefully work with natively compatible drivers.
195
+ Under certain circumstances, like running system tests using chromedriver under CI (which may be resource constrained and trigger errors in certain cases), you may want to explicitly turn off including the shim. You can do this by calling the bulk tag helper with `javascript_importmap_tags("application", shim: false)`. Thus you can pass in something like `shim: !ENV["CI"]`. If you want, and are sure you're not doing any full-page caching, you can also connect this directive to a user agent check (using a gem like `useragent`) to check whether the browser is chrome/edge 89+. But you really shouldn't have to, as the shim is designed to gracefully work with natively compatible drivers.
196
196
 
197
197
 
198
198
  ## A note about browser extensions
199
199
 
200
- Certain extensions that also load Javascript modules may block import maps from being loaded (for instance, the Apollo Client Devtools extension). If you see a console message like `An import map is added after module script load was triggered`, browser extensions are likely the culprit.
200
+ Certain extensions that also load JavaScript modules may block import maps from being loaded (for instance, the Apollo Client Devtools extension). If you see a console message like `An import map is added after module script load was triggered`, browser extensions are likely the culprit.
201
201
 
202
202
 
203
203
  ## License
@@ -1,8 +1,6 @@
1
- /* ES Module Shims CSP 0.15.1 */
1
+ /* ES Module Shims 1.0.4 */
2
2
  (function () {
3
3
 
4
- Promise.resolve();
5
-
6
4
  const edge = navigator.userAgent.match(/Edge\/\d\d\.\d+$/);
7
5
 
8
6
  let baseUrl;
@@ -203,7 +201,7 @@
203
201
  let shimMode = !!esmsInitOptions$1.shimMode;
204
202
  const resolveHook = shimMode && esmsInitOptions$1.resolve;
205
203
 
206
- const skip = esmsInitOptions$1.skip ? new RegExp(esmsInitOptions$1.skip) : /^https:\/\/(cdn\.skypack\.dev|jspm\.dev)\//;
204
+ const skip = esmsInitOptions$1.skip ? new RegExp(esmsInitOptions$1.skip) : null;
207
205
 
208
206
  let nonce = esmsInitOptions$1.nonce;
209
207
 
@@ -331,7 +329,35 @@
331
329
 
332
330
  let importMap = { imports: {}, scopes: {} };
333
331
  let importMapSrcOrLazy = false;
334
- let importMapPromise = featureDetectionPromise;
332
+ let baselinePassthrough;
333
+
334
+ const initPromise = featureDetectionPromise.then(() => {
335
+ baselinePassthrough = supportsDynamicImport && supportsImportMeta && supportsImportMaps && (!jsonModulesEnabled || supportsJsonAssertions) && (!cssModulesEnabled || supportsCssAssertions) && !importMapSrcOrLazy && !false;
336
+ // shim mode is determined on initialization, no late shim mode
337
+ if (!shimMode && document.querySelectorAll('script[type="module-shim"],script[type="importmap-shim"]').length)
338
+ setShimMode();
339
+ if (shimMode || !baselinePassthrough) {
340
+ new MutationObserver(mutations => {
341
+ for (const mutation of mutations) {
342
+ if (mutation.type !== 'childList') continue;
343
+ for (const node of mutation.addedNodes) {
344
+ if (node.tagName === 'SCRIPT') {
345
+ if (!shimMode && node.type === 'module' || shimMode && node.type === 'module-shim')
346
+ processScript(node);
347
+ if (!shimMode && node.type === 'importmap' || shimMode && node.type === 'importmap-shim')
348
+ processImportMap(node);
349
+ }
350
+ else if (node.tagName === 'LINK' && node.rel === 'modulepreload')
351
+ processPreload(node);
352
+ }
353
+ }
354
+ }).observe(document, { childList: true, subtree: true });
355
+ processImportMaps();
356
+ processScriptsAndPreloads();
357
+ return undefined;
358
+ }
359
+ });
360
+ let importMapPromise = initPromise;
335
361
 
336
362
  let acceptingImportMaps = true;
337
363
  let nativeAcceptingImportMaps = true;
@@ -346,21 +372,20 @@
346
372
  }
347
373
  await importMapPromise;
348
374
  // early analysis opt-out - no need to even fetch if we have feature support
349
- if (!shimMode && supportsDynamicImport && supportsImportMeta && supportsImportMaps && (!jsonModulesEnabled || supportsJsonAssertions) && (!cssModulesEnabled || supportsCssAssertions) && !importMapSrcOrLazy) {
375
+ if (!shimMode && baselinePassthrough) {
350
376
  // for polyfill case, only dynamic import needs a return value here, and dynamic import will never pass nativelyLoaded
351
377
  if (nativelyLoaded)
352
378
  return null;
353
379
  await lastStaticLoadPromise;
354
380
  return dynamicImport(source ? createBlob(source) : url, { errUrl: url || source });
355
381
  }
356
- await undefined;
357
382
  const load = getOrCreateLoad(url, fetchOpts, source);
358
383
  const seen = {};
359
384
  await loadAll(load, seen);
360
385
  lastLoad = undefined;
361
386
  resolveDeps(load, seen);
362
387
  await lastStaticLoadPromise;
363
- if (source && !shimMode && !load.n) {
388
+ if (source && !shimMode && !load.n && !false) {
364
389
  const module = await dynamicImport(createBlob(source), { errUrl: source });
365
390
  if (revokeBlobURLs) revokeObjectURLs(Object.keys(seen));
366
391
  return module;
@@ -393,7 +418,17 @@
393
418
  }
394
419
 
395
420
  async function importShim (id, parentUrl = baseUrl, _assertion) {
396
- processScripts();
421
+ // needed for shim check
422
+ await initPromise;
423
+ if (acceptingImportMaps || shimMode || !baselinePassthrough) {
424
+ processImportMaps();
425
+ if (!shimMode) {
426
+ acceptingImportMaps = false;
427
+ }
428
+ else {
429
+ nativeAcceptingImportMaps = false;
430
+ }
431
+ }
397
432
  await importMapPromise;
398
433
  return topLevelLoad((await resolve(id, parentUrl)).r || throwUnresolved(id, parentUrl), { credentials: 'same-origin' });
399
434
  }
@@ -403,7 +438,6 @@
403
438
  const meta = {};
404
439
 
405
440
  async function importMetaResolve (id, parentUrl = this.url) {
406
- await importMapPromise;
407
441
  return (await resolve(id, `${parentUrl}`)).r || throwUnresolved(id, parentUrl);
408
442
  }
409
443
 
@@ -490,17 +524,11 @@
490
524
  resolvedSource += source.slice(lastIndex);
491
525
  }
492
526
 
493
- resolvedSource = resolvedSource.replace(/\/\/# sourceMappingURL=(.*)\s*$/, (match, url) => {
494
- return match.replace(url, new URL(url, load.r));
495
- });
527
+ resolvedSource = resolvedSource.replace(/\/\/# sourceMappingURL=(.*)\s*$/, (match, url) => match.replace(url, () => new URL(url, load.r)));
496
528
  let hasSourceURL = false;
497
- resolvedSource = resolvedSource.replace(/\/\/# sourceURL=(.*)\s*$/, (match, url) => {
498
- hasSourceURL = true;
499
- return match.replace(url, new URL(url, load.r));
500
- });
501
- if (!hasSourceURL) {
529
+ resolvedSource = resolvedSource.replace(/\/\/# sourceURL=(.*)\s*$/, (match, url) => (hasSourceURL = true, match.replace(url, () => new URL(url, load.r))));
530
+ if (!hasSourceURL)
502
531
  resolvedSource += '\n//# sourceURL=' + load.r;
503
- }
504
532
 
505
533
  load.b = lastLoad = createBlob(resolvedSource);
506
534
  load.S = undefined;
@@ -617,7 +645,7 @@
617
645
  if (d !== -1) return;
618
646
  if (!r)
619
647
  throwUnresolved(n, load.r || load.u);
620
- if (skip.test(r)) return { b: r };
648
+ if (skip && skip.test(r)) return { b: r };
621
649
  if (childFetchOpts.integrity)
622
650
  childFetchOpts = Object.assign({}, childFetchOpts, { integrity: undefined });
623
651
  return getOrCreateLoad(r, childFetchOpts).f;
@@ -627,22 +655,16 @@
627
655
  return load;
628
656
  }
629
657
 
630
- const scriptQuery = 'script[type="module-shim"],script[type="importmap-shim"],script[type="module"],script[type="importmap"]';
631
- const preloadQuery = 'link[rel="modulepreload"]';
632
-
633
- function processScripts () {
634
- for (const link of document.querySelectorAll(preloadQuery))
635
- processPreload(link);
636
- const scripts = document.querySelectorAll(scriptQuery);
637
- // early shim mode opt-in
638
- if (!shimMode) {
639
- for (const script of scripts) {
640
- if (script.type.endsWith('-shim'))
641
- setShimMode();
642
- }
643
- }
644
- for (const script of scripts)
658
+ function processScriptsAndPreloads () {
659
+ for (const script of document.querySelectorAll(shimMode ? 'script[type="module-shim"]' : 'script[type="module"]'))
645
660
  processScript(script);
661
+ for (const link of document.querySelectorAll('link[rel="modulepreload"]'))
662
+ processPreload(link);
663
+ }
664
+
665
+ function processImportMaps () {
666
+ for (const script of document.querySelectorAll(shimMode ? 'script[type="importmap-shim"]' : 'script[type="importmap"]'))
667
+ processImportMap(script);
646
668
  }
647
669
 
648
670
  function getFetchOpts (script) {
@@ -668,73 +690,74 @@
668
690
  document.dispatchEvent(new Event('DOMContentLoaded'));
669
691
  }
670
692
  // this should always trigger because we assume es-module-shims is itself a domcontentloaded requirement
671
- document.addEventListener('DOMContentLoaded', domContentLoadedCheck);
693
+ document.addEventListener('DOMContentLoaded', async () => {
694
+ await initPromise;
695
+ domContentLoadedCheck();
696
+ if (shimMode || !baselinePassthrough) {
697
+ processImportMaps();
698
+ processScriptsAndPreloads();
699
+ }
700
+ });
672
701
 
673
702
  let readyStateCompleteCnt = 1;
674
703
  if (document.readyState === 'complete')
675
704
  readyStateCompleteCheck();
676
705
  else
677
- document.addEventListener('readystatechange', readyStateCompleteCheck);
706
+ document.addEventListener('readystatechange', async () => {
707
+ await initPromise;
708
+ readyStateCompleteCheck();
709
+ });
678
710
  function readyStateCompleteCheck () {
679
711
  if (--readyStateCompleteCnt === 0 && !noLoadEventRetriggers)
680
712
  document.dispatchEvent(new Event('readystatechange'));
681
713
  }
682
714
 
683
- function processScript (script) {
684
- if (script.ep) // ep marker = script processed
715
+ function processImportMap (script) {
716
+ if (!acceptingImportMaps)
685
717
  return;
686
- const shim = script.type.endsWith('-shim');
687
- if (shim && !shimMode) setShimMode();
688
- const type = shimMode ? script.type.slice(0, -5) : script.type;
689
- // dont process module scripts in shim mode or noshim module scripts in polyfill mode
690
- if (!shim && shimMode || script.getAttribute('noshim') !== null)
718
+ if (script.ep) // ep marker = script processed
691
719
  return;
692
720
  // empty inline scripts sometimes show before domready
693
721
  if (!script.src && !script.innerHTML)
694
722
  return;
695
723
  script.ep = true;
696
- if (type === 'module') {
697
- // does this load block readystate complete
698
- const isReadyScript = readyStateCompleteCnt > 0;
699
- // does this load block DOMContentLoaded
700
- const isDomContentLoadedScript = domContentLoadedCnt > 0;
701
- if (isReadyScript) readyStateCompleteCnt++;
702
- if (isDomContentLoadedScript) domContentLoadedCnt++;
703
- const loadPromise = topLevelLoad(script.src || `${baseUrl}?${id++}`, getFetchOpts(script), !script.src && script.innerHTML, !shimMode, isReadyScript && lastStaticLoadPromise).then(() => {
704
- if (!noLoadEventRetriggers)
705
- triggerLoadEvent(script);
706
- }).catch(e => {
707
- if (!noLoadEventRetriggers)
708
- triggerLoadEvent(script);
709
- // setTimeout(() => { throw e; });
710
- onerror(e);
711
- });
712
- if (isReadyScript)
713
- lastStaticLoadPromise = loadPromise.then(readyStateCompleteCheck);
714
- if (isDomContentLoadedScript)
715
- loadPromise.then(domContentLoadedCheck);
724
+ // we dont currently support multiple, external or dynamic imports maps in polyfill mode to match native
725
+ if (script.src || !nativeAcceptingImportMaps) {
726
+ if (!shimMode)
727
+ return;
728
+ importMapSrcOrLazy = true;
716
729
  }
717
- else if (acceptingImportMaps && type === 'importmap') {
718
- // we dont currently support multiple, external or dynamic imports maps in polyfill mode to match native
719
- if (script.src || !nativeAcceptingImportMaps) {
720
- if (!shimMode)
721
- return;
722
- importMapSrcOrLazy = true;
723
- }
724
- if (!shimMode) {
725
- acceptingImportMaps = false;
726
- }
727
- else {
728
- nativeAcceptingImportMaps = false;
729
- }
730
- importMapPromise = importMapPromise.then(async () => {
731
- importMap = resolveAndComposeImportMap(script.src ? await (await fetchHook(script.src)).json() : JSON.parse(script.innerHTML), script.src || baseUrl, importMap);
732
- });
730
+ if (!shimMode) {
731
+ acceptingImportMaps = false;
732
+ }
733
+ else {
734
+ nativeAcceptingImportMaps = false;
733
735
  }
736
+ importMapPromise = importMapPromise.then(async () => {
737
+ importMap = resolveAndComposeImportMap(script.src ? await (await fetchHook(script.src)).json() : JSON.parse(script.innerHTML), script.src || baseUrl, importMap);
738
+ });
734
739
  }
735
740
 
736
- function triggerLoadEvent (script) {
737
- script.dispatchEvent(new Event('load'));
741
+ function processScript (script) {
742
+ if (script.ep) // ep marker = script processed
743
+ return;
744
+ if (script.getAttribute('noshim') !== null)
745
+ return;
746
+ // empty inline scripts sometimes show before domready
747
+ if (!script.src && !script.innerHTML)
748
+ return;
749
+ script.ep = true;
750
+ // does this load block readystate complete
751
+ const isReadyScript = readyStateCompleteCnt > 0;
752
+ // does this load block DOMContentLoaded
753
+ const isDomContentLoadedScript = domContentLoadedCnt > 0;
754
+ if (isReadyScript) readyStateCompleteCnt++;
755
+ if (isDomContentLoadedScript) domContentLoadedCnt++;
756
+ const loadPromise = topLevelLoad(script.src || `${baseUrl}?${id++}`, getFetchOpts(script), !script.src && script.innerHTML, !shimMode, isReadyScript && lastStaticLoadPromise).catch(onerror);
757
+ if (isReadyScript)
758
+ lastStaticLoadPromise = loadPromise.then(readyStateCompleteCheck);
759
+ if (isDomContentLoadedScript)
760
+ loadPromise.then(domContentLoadedCheck);
738
761
  }
739
762
 
740
763
  const fetchCache = {};
@@ -747,22 +770,8 @@
747
770
  fetchCache[link.href] = doFetch(link.href, getFetchOpts(link));
748
771
  }
749
772
 
750
- new MutationObserver(mutations => {
751
- for (const mutation of mutations) {
752
- if (mutation.type !== 'childList') continue;
753
- for (const node of mutation.addedNodes) {
754
- if (node.tagName === 'SCRIPT' && node.type)
755
- processScript(node);
756
- else if (node.tagName === 'LINK' && node.rel === 'modulepreload')
757
- processPreload(node);
758
- }
759
- }
760
- }).observe(document, { childList: true, subtree: true });
761
-
762
773
  function throwUnresolved (id, parentUrl) {
763
774
  throw Error("Unable to resolve specifier '" + id + (parentUrl ? "' from " + parentUrl : "'"));
764
775
  }
765
776
 
766
- processScripts();
767
-
768
- }());
777
+ }());
@@ -43,6 +43,7 @@ class Importmap::Commands < Thor
43
43
 
44
44
  desc "json", "Show the full importmap in json"
45
45
  def json
46
+ require Rails.root.join("config/environment")
46
47
  puts Rails.application.importmap.to_json(resolver: ActionController::Base.helpers)
47
48
  end
48
49
 
data/lib/importmap/map.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require "pathname"
2
- require "active_support/evented_file_update_checker"
3
2
 
4
3
  class Importmap::Map
5
4
  attr_reader :packages, :directories
@@ -63,11 +62,11 @@ class Importmap::Map
63
62
  def cache_sweeper(watches: nil)
64
63
  if watches
65
64
  @cache_sweeper =
66
- ActiveSupport::EventedFileUpdateChecker.new([], Array(watches).collect { |dir| [ dir, "js"] }.to_h) do
65
+ Rails.application.config.file_watcher.new([], Array(watches).collect { |dir| [ dir.to_s, "js"] }.to_h) do
67
66
  clear_cache
68
67
  end
69
68
  else
70
- @cache_sweeper
69
+ @cache_sweeper
71
70
  end
72
71
  end
73
72
 
@@ -1,3 +1,3 @@
1
1
  module Importmap
2
- VERSION = "0.7.1"
2
+ VERSION = "0.7.5"
3
3
  end
@@ -3,10 +3,4 @@ namespace :importmap do
3
3
  task :install do
4
4
  system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/install.rb", __dir__)}"
5
5
  end
6
-
7
- desc "Show the importmap"
8
- task :pins do
9
- require Rails.root.join("config/environment")
10
- puts Rails.application.importmap.to_json(resolver: ActionController::Base.helpers)
11
- end
12
6
  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: 0.7.1
4
+ version: 0.7.5
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: 2021-09-20 00:00:00.000000000 Z
11
+ date: 2021-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 6.0.0
27
- - !ruby/object:Gem::Dependency
28
- name: listen
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '3.7'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '3.7'
41
27
  description:
42
28
  email: david@loudthinking.com
43
29
  executables: []