propshaft 0.7.0 → 0.8.0

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: a149fdc0fb45487422a71e21df47105ee0071e23f752f596f54cd98400bc99e2
4
- data.tar.gz: 9dcd99aa258a91aa99ac46f1da9379712d836f06c42cd8ce9e6df8b020cc94c6
3
+ metadata.gz: 56736cd8d13ffa9511e5cd47d39e3d3849f66484f0ba489686b75aa5a5c57936
4
+ data.tar.gz: 7adfc7103ca6694027ad577b7cd14bf6972227f02bdf0bd0659d508371afdfad
5
5
  SHA512:
6
- metadata.gz: 79779f26c1d121049451c5a8d7545e9fbfbcdd2b01a966f89fa0a23aa2b140ea2932828bd4c1b9edbab8be106366f8f92f9daa91bfa1c7af2207619a6fcce9fe
7
- data.tar.gz: 7f609b53f85ef6bdeb53972c11d9a54301cd974c7d5573d5d93fbeb043daed863e08407bb95b45d7c8a55a122770dcb5f9f8b2d55f6830c2adbb5465281613ad
6
+ metadata.gz: 67c4c686072bc75784519f8043225b9bb462a19a74a2617ec1628a25cb701bad1aabe05a873126038718b6bd18ba9d51f47cdd0daa89418186996832a0f5707c
7
+ data.tar.gz: f476c9aff5b7975df5815095bdf1917eeb748ee1c9ebab0f058aa670863597a6d4794c77b3bd379eafb355c83b9fa8008b366796ad52188d7804410f93c8ec33
data/README.md CHANGED
@@ -49,7 +49,7 @@ But for greenfield apps using the default import-map approach, Propshaft can als
49
49
 
50
50
  ## Will Propshaft replace Sprockets as the Rails default?
51
51
 
52
- Most likely, but Sprockets need to be supported as well for a long time to come. Plenty of apps and gems were built on Sprocket features, and they won't be migrating soon. Still working out the compatibility story. This is very much alpha software at the moment.
52
+ Most likely, but Sprockets need to be supported as well for a long time to come. Plenty of apps and gems were built on Sprocket features, and they won't be migrating soon. Still working out the compatibility story. This is very much beta software at the moment.
53
53
 
54
54
 
55
55
  ## License
@@ -4,8 +4,8 @@ require "propshaft/resolver/static"
4
4
  require "propshaft/server"
5
5
  require "propshaft/processor"
6
6
  require "propshaft/compilers"
7
- require "propshaft/compilers/css_asset_urls"
8
- require "propshaft/compilers/source_mapping_urls"
7
+ require "propshaft/compiler/css_asset_urls"
8
+ require "propshaft/compiler/source_mapping_urls"
9
9
 
10
10
  class Propshaft::Assembly
11
11
  attr_reader :config
@@ -2,15 +2,10 @@ require "digest/sha1"
2
2
  require "action_dispatch/http/mime_type"
3
3
 
4
4
  class Propshaft::Asset
5
- PREDIGESTED_REGEX = /-([0-9a-zA-Z]{7,128}\.digested)/
6
-
7
5
  attr_reader :path, :logical_path, :version
8
6
 
9
7
  def initialize(path, logical_path:, version: nil)
10
- @path = path
11
- @digest = logical_path.to_s[PREDIGESTED_REGEX, 1]
12
- @logical_path = Pathname.new(@digest ? logical_path.sub("-#{@digest}", "") : logical_path)
13
- @version = version
8
+ @path, @logical_path, @version = path, Pathname.new(logical_path), version
14
9
  end
15
10
 
16
11
  def content
@@ -30,14 +25,23 @@ class Propshaft::Asset
30
25
  end
31
26
 
32
27
  def digested_path
33
- logical_path.sub(/\.(\w+)$/) { |ext| "-#{digest}#{ext}" }
28
+ if already_digested?
29
+ logical_path
30
+ else
31
+ logical_path.sub(/\.(\w+)$/) { |ext| "-#{digest}#{ext}" }
32
+ end
34
33
  end
35
34
 
36
35
  def fresh?(digest)
37
- self.digest == digest
36
+ self.digest == digest || already_digested?
38
37
  end
39
38
 
40
39
  def ==(other_asset)
41
40
  logical_path.hash == other_asset.logical_path.hash
42
41
  end
42
+
43
+ private
44
+ def already_digested?
45
+ logical_path.to_s =~ /-([0-9a-zA-Z]{7,128})\.digested/
46
+ end
43
47
  end
@@ -1,15 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Propshaft::Compilers::CssAssetUrls
4
- attr_reader :assembly, :url_prefix
3
+ require "propshaft/compiler"
5
4
 
5
+ class Propshaft::Compiler::CssAssetUrls < Propshaft::Compiler
6
6
  ASSET_URL_PATTERN = /url\(\s*["']?(?!(?:\#|%23|data|http|\/\/))([^"'\s?#)]+)([#?][^"')]+)?\s*["']?\)/
7
7
 
8
- def initialize(assembly)
9
- @assembly = assembly
10
- @url_prefix = File.join(assembly.config.host.to_s, assembly.config.prefix.to_s).chomp("/")
11
- end
12
-
13
8
  def compile(logical_path, input)
14
9
  input.gsub(ASSET_URL_PATTERN) { asset_url resolve_path(logical_path.dirname, $1), logical_path, $2, $1 }
15
10
  end
@@ -1,16 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Propshaft::Compilers::SourceMappingUrls
4
- attr_reader :assembly
3
+ require "propshaft/compiler"
5
4
 
6
- SOURCE_MAPPING_PATTERN = %r{^(//|/\*)# sourceMappingURL=(.+\.map)}
7
-
8
- def initialize(assembly)
9
- @assembly = assembly
10
- end
5
+ class Propshaft::Compiler::SourceMappingUrls < Propshaft::Compiler
6
+ SOURCE_MAPPING_PATTERN = %r{(//|/\*)# sourceMappingURL=(.+\.map)(\s*?\*\/)?\s*?\Z}
11
7
 
12
8
  def compile(logical_path, input)
13
- input.gsub(SOURCE_MAPPING_PATTERN) { source_mapping_url(asset_path($2, logical_path), $1) }
9
+ input.gsub(SOURCE_MAPPING_PATTERN) { source_mapping_url(asset_path($2, logical_path), $1, $3) }
14
10
  end
15
11
 
16
12
  private
@@ -22,12 +18,12 @@ class Propshaft::Compilers::SourceMappingUrls
22
18
  end
23
19
  end
24
20
 
25
- def source_mapping_url(resolved_path, comment)
21
+ def source_mapping_url(resolved_path, comment_start, comment_end)
26
22
  if asset = assembly.load_path.find(resolved_path)
27
- "#{comment}# sourceMappingURL=#{assembly.config.prefix}/#{asset.digested_path}"
23
+ "#{comment_start}# sourceMappingURL=#{url_prefix}/#{asset.digested_path}#{comment_end}"
28
24
  else
29
25
  Propshaft.logger.warn "Removed sourceMappingURL comment for missing asset '#{resolved_path}' from #{resolved_path}"
30
- nil
26
+ "#{comment_start}#{comment_end}"
31
27
  end
32
28
  end
33
29
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Base compiler from which other compilers can inherit
4
+ class Propshaft::Compiler
5
+ attr_reader :assembly
6
+
7
+ def initialize(assembly)
8
+ @assembly = assembly
9
+ end
10
+
11
+ # Override this in a specific compiler
12
+ def compile(logical_path, input)
13
+ raise NotImplementedError
14
+ end
15
+
16
+ private
17
+ def url_prefix
18
+ @url_prefix ||= File.join(assembly.config.relative_url_root.to_s, assembly.config.prefix.to_s).chomp("/")
19
+ end
20
+ end
@@ -3,5 +3,23 @@ module Propshaft
3
3
  def compute_asset_path(path, options = {})
4
4
  Rails.application.assets.resolver.resolve(path) || raise(MissingAssetError.new(path))
5
5
  end
6
+
7
+ # Add an option to call `stylesheet_link_tag` with `:all` to include every css file found on the load path.
8
+ def stylesheet_link_tag(*sources)
9
+ if sources.first == :all
10
+ super *all_stylesheets_paths
11
+ else
12
+ super
13
+ end
14
+ end
15
+
16
+ # Returns a sorted and unique array of logical paths for all stylesheets in the load path.
17
+ def all_stylesheets_paths
18
+ Rails.application.assets.load_path
19
+ .assets(content_types: [ Mime::EXTENSION_LOOKUP["css"] ])
20
+ .collect { |css| css.logical_path.to_s }
21
+ .sort
22
+ .uniq
23
+ end
6
24
  end
7
25
  end
@@ -48,8 +48,7 @@ class Propshaft::LoadPath
48
48
  paths.each do |path|
49
49
  without_dotfiles(all_files_from_tree(path)).each do |file|
50
50
  logical_path = file.relative_path_from(path)
51
- asset = Propshaft::Asset.new(file, logical_path: logical_path, version: version)
52
- mapped[asset.logical_path.to_s] ||= asset
51
+ mapped[logical_path.to_s] ||= Propshaft::Asset.new(file, logical_path: logical_path, version: version)
53
52
  end if path.exist?
54
53
  end
55
54
  end
@@ -42,7 +42,7 @@ class Propshaft::OutputPath
42
42
  modified_at = [ 0, Time.now - mtime ].max
43
43
  modified_at < expires_at || limit < count
44
44
  end
45
-
45
+
46
46
  def remove(path)
47
47
  FileUtils.rm(@path.join(path))
48
48
  Propshaft.logger.info "Removed #{path}"
@@ -11,13 +11,13 @@ module Propshaft
11
11
  config.assets.prefix = "/assets"
12
12
  config.assets.quiet = false
13
13
  config.assets.compilers = [
14
- [ "text/css", Propshaft::Compilers::CssAssetUrls ],
15
- [ "text/css", Propshaft::Compilers::SourceMappingUrls ],
16
- [ "text/javascript", Propshaft::Compilers::SourceMappingUrls ]
14
+ [ "text/css", Propshaft::Compiler::CssAssetUrls ],
15
+ [ "text/css", Propshaft::Compiler::SourceMappingUrls ],
16
+ [ "text/javascript", Propshaft::Compiler::SourceMappingUrls ]
17
17
  ]
18
18
  config.assets.sweep_cache = Rails.env.development?
19
19
  config.assets.server = Rails.env.development? || Rails.env.test?
20
- config.assets.host = nil
20
+ config.assets.relative_url_root = nil
21
21
 
22
22
  # Register propshaft initializer to copy the assets path in all the Rails Engines.
23
23
  # This makes possible for us to keep all `assets` config in this Railtie, but still
@@ -31,7 +31,7 @@ module Propshaft
31
31
  end
32
32
 
33
33
  config.after_initialize do |app|
34
- config.assets.host = app.config.asset_host
34
+ config.assets.relative_url_root ||= app.config.relative_url_root
35
35
  config.assets.output_path ||=
36
36
  Pathname.new(File.join(app.config.paths["public"].first, app.config.assets.prefix))
37
37
 
@@ -4,7 +4,7 @@ namespace :assets do
4
4
  Rails.application.assets.processor.process
5
5
  if Rails.env.development?
6
6
  puts "Warning: You are precompiling assets in development. Rails will not " \
7
- "serve any changed assets until you delete public/assets/.manifest.json"
7
+ "serve any changed assets until you delete public#{Rails.application.config.assets.prefix}/.manifest.json"
8
8
  end
9
9
  end
10
10
 
@@ -14,16 +14,16 @@ class Propshaft::Server
14
14
  [
15
15
  200,
16
16
  {
17
- "content-length" => compiled_content.length.to_s,
18
- "content-type" => asset.content_type.to_s,
19
- "accept-encoding" => "vary",
20
- "etag" => asset.digest,
21
- "cache-control" => "public, max-age=31536000, immutable"
17
+ Rack::CONTENT_LENGTH => compiled_content.length.to_s,
18
+ Rack::CONTENT_TYPE => asset.content_type.to_s,
19
+ VARY => "Accept-Encoding",
20
+ Rack::ETAG => asset.digest,
21
+ Rack::CACHE_CONTROL => "public, max-age=31536000, immutable"
22
22
  },
23
23
  [ compiled_content ]
24
24
  ]
25
25
  else
26
- [ 404, { "content-type" => "text/plain", "content-length" => "9" }, [ "Not found" ] ]
26
+ [ 404, { Rack::CONTENT_TYPE => "text/plain", Rack::CONTENT_LENGTH => "9" }, [ "Not found" ] ]
27
27
  end
28
28
  end
29
29
 
@@ -34,9 +34,15 @@ class Propshaft::Server
34
34
  private
35
35
  def extract_path_and_digest(env)
36
36
  full_path = Rack::Utils.unescape(env["PATH_INFO"].to_s.sub(/^\//, ""))
37
- digest = full_path[/-([0-9a-zA-Z]{7,128}(?:\.digested)?)\.[^.]+\z/, 1]
37
+ digest = full_path[/-([0-9a-zA-Z]{7,128})\.(?!digested)[^.]+\z/, 1]
38
38
  path = digest ? full_path.sub("-#{digest}", "") : full_path
39
39
 
40
40
  [ path, digest ]
41
41
  end
42
+
43
+ if Gem::Version.new(Rack::RELEASE) < Gem::Version.new("3")
44
+ VARY = "Vary"
45
+ else
46
+ VARY = "vary"
47
+ end
42
48
  end
@@ -1,3 +1,3 @@
1
1
  module Propshaft
2
- VERSION = "0.7.0"
2
+ VERSION = "0.8.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: propshaft
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
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: 2023-03-04 00:00:00.000000000 Z
11
+ date: 2023-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -78,9 +78,10 @@ files:
78
78
  - lib/propshaft.rb
79
79
  - lib/propshaft/assembly.rb
80
80
  - lib/propshaft/asset.rb
81
+ - lib/propshaft/compiler.rb
82
+ - lib/propshaft/compiler/css_asset_urls.rb
83
+ - lib/propshaft/compiler/source_mapping_urls.rb
81
84
  - lib/propshaft/compilers.rb
82
- - lib/propshaft/compilers/css_asset_urls.rb
83
- - lib/propshaft/compilers/source_mapping_urls.rb
84
85
  - lib/propshaft/errors.rb
85
86
  - lib/propshaft/helper.rb
86
87
  - lib/propshaft/load_path.rb
@@ -113,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
114
  - !ruby/object:Gem::Version
114
115
  version: '0'
115
116
  requirements: []
116
- rubygems_version: 3.4.6
117
+ rubygems_version: 3.4.20
117
118
  signing_key:
118
119
  specification_version: 4
119
120
  summary: Deliver assets for Rails.