Class: Proscenium::Importer

Inherits:
ActiveSupport::CurrentAttributes
  • Object
show all
Defined in:
lib/proscenium/importer.rb

Constant Summary collapse

JS_EXTENSIONS =
%w[.tsx .ts .jsx .js].freeze
CSS_EXTENSIONS =
%w[.module.css .css].freeze

Class Method Summary collapse

Class Method Details

.css_imported?Boolean

Returns:

  • (Boolean)


163
164
165
# File 'lib/proscenium/importer.rb', line 163

def css_imported?
  imported&.keys&.any? { |x| x.end_with?(*CSS_EXTENSIONS) }
end

.each_javascript(delete: false) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
# File 'lib/proscenium/importer.rb', line 151

def each_javascript(delete: false)
  return if imported.blank?

  blk = proc do |key, options|
    if key.end_with?(*JS_EXTENSIONS)
      yield(key, options)
      true
    end
  end
  delete ? imported.delete_if(&blk) : imported.each(&blk)
end

.each_stylesheet(delete: false) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/proscenium/importer.rb', line 138

def each_stylesheet(delete: false)
  return if imported.blank?

  blk = proc do |key, options|
    if key.end_with?(*CSS_EXTENSIONS)
      yield(key, options)
      true
    end
  end

  delete ? imported.delete_if(&blk) : imported.each(&blk)
end

.import(filepath = nil, sideloaded: false) ⇒ String|nil

Import the given ‘filepath`. This is idempotent - it will never include duplicates.

Parameters:

  • filepath (String) (defaults to: nil)

    Absolute URL path (relative to Rails root) of the file to import. Should be the actual asset file, eg. app.css, some/component.js.

Returns:

  • (String|nil)

    the digest of the imported file path if a css module (*.module.css).



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/proscenium/importer.rb', line 27

def import(filepath = nil, sideloaded: false, **)
  self.imported ||= {}

  digest = nil

  if filepath.end_with?('.module.css')
    if self.imported.key?(filepath)
      digest = self.imported[filepath][:digest]
      abs_path = self.imported[filepath][:abs_path]
    else
      manifest_path, non_manifest_path, abs_path = Resolver.resolve(filepath, as_array: true)
      digest = Utils.css_module_digest(abs_path)
      filepath = Array(manifest_path || non_manifest_path)[0]

      if sideloaded
        ActiveSupport::Notifications.instrument 'sideload.proscenium', identifier: filepath,
                                                                       sideloaded: do
          self.imported[filepath] = { ** }
          self.imported[filepath][:digest] = digest
          self.imported[filepath][:abs_path] = abs_path
        end
      else
        self.imported[filepath] = { ** }
        self.imported[filepath][:digest] = digest
        self.imported[filepath][:abs_path] = abs_path
      end
    end

    transformed_path = ''
    if Proscenium.config.debug || Rails.env.development?
      rel_path = Pathname.new(abs_path).relative_path_from(Rails.root).sub_ext('')
      transformed_path = "_#{rel_path.to_s.gsub(%r{[@/.+]}, '-')}"
    end

    "#{digest}#{transformed_path}"
  else
    return if self.imported.key?(filepath)

    Array(Resolver.resolve(filepath)).each do |fp|
      if sideloaded
        ActiveSupport::Notifications.instrument 'sideload.proscenium', identifier: fp,
                                                                       sideloaded: do
          self.imported[fp] = { ** }
        end
      else
        self.imported[fp] = { ** }
      end
    end
  end
end

.imported?(filepath = nil) ⇒ Boolean

Returns:

  • (Boolean)


171
172
173
# File 'lib/proscenium/importer.rb', line 171

def imported?(filepath = nil)
  filepath ? imported&.key?(filepath) : !imported.blank?
end

.js_imported?Boolean

Returns:

  • (Boolean)


167
168
169
# File 'lib/proscenium/importer.rb', line 167

def js_imported?
  imported&.keys&.any? { |x| x.end_with?(*JS_EXTENSIONS) }
end

.sideload(filepath, **options) ⇒ Object

Sideloads JS and CSS assets for the given Ruby filepath.

Any files with the same base name and matching a supported extension will be sideloaded. Only one JS and one CSS file will be sideloaded, with the first match used in the following order:

- JS extensions: .tsx, .ts, .jsx, and .js.
- CSS extensions: .css.module, and .css.

Example:

- `app/views/layouts/application.rb`
- `app/views/layouts/application.css`
- `app/views/layouts/application.js`
- `app/views/layouts/application.tsx`

A request to sideload ‘app/views/layouts/application.rb` will result in `application.css` and `application.tsx` being sideloaded. `application.js` will not be sideloaded because the `.tsx` extension is matched first.

Parameters:

  • filepath (Pathname)

    Absolute file system path of the Ruby file to sideload.

  • options (Hash)

    Options to pass to ‘import`.



98
99
100
101
102
103
# File 'lib/proscenium/importer.rb', line 98

def sideload(filepath, **options)
  return if !Proscenium.config.side_load || (options[:js] == false && options[:css] == false)

  sideload_js(filepath, **options) unless options[:js] == false
  sideload_css(filepath, **options) unless options[:css] == false
end

.sideload_css(filepath) ⇒ Object



109
110
111
# File 'lib/proscenium/importer.rb', line 109

def sideload_css(filepath, **)
  _sideload(filepath, ['.css'], **)
end

.sideload_css_module(filepath) ⇒ Object



113
114
115
# File 'lib/proscenium/importer.rb', line 113

def sideload_css_module(filepath, **)
  _sideload(filepath, ['.module.css'], **)
end

.sideload_js(filepath) ⇒ Object



105
106
107
# File 'lib/proscenium/importer.rb', line 105

def sideload_js(filepath, **)
  _sideload(filepath, JS_EXTENSIONS, **)
end