propshaft 0.5.0 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ed27e836fd19bb9d9293ca1fad143a3aa6454c40e671891cd47cfd279524d16f
4
- data.tar.gz: fa7b4f0f3dd48634b0d9f5ba012bc1d90d43445aee137846c6a9e66c96754e6a
3
+ metadata.gz: 2e186c6a8b298be03fa1f414751bf99e425614701c2283eafeafc49d14a10dd9
4
+ data.tar.gz: d447859d4a45ae4d7f62b54d71a9ce5c4d15d2151c98a3369cd33229587a1441
5
5
  SHA512:
6
- metadata.gz: daea545ac84a7c13ddb0198544f3058fbde3ccf9dfa42302f705613f4ec06c8c9962e2ffebe8276a9cc97912122ee8b8591c246f0ff09d6a91124c49b142bd09
7
- data.tar.gz: '09355d57890f7b5ac3372f9d76dd08784f2e2b1de7b83f099ef8c9f3eebd73d53a2247e58df0e7ca0c59247bbb1478d4e6ec68e260d599e8002c2ad367779439'
6
+ metadata.gz: 337241f55febf946b0b4e508012d3f8737882c8fc92665f84a6d407ec52a93acd9c11840f456897f8100294665ce4dac5ae6b70c79ca08b25479c6cf4689877e
7
+ data.tar.gz: e436e82a80404f84eb27e32e493d38bda181e80b08b8c0ca788a69354bd97eef51b2c73ddfff62ebeb6407ecf553b15a290bf5680d7e2fcd7150ede657675dcb
data/README.md CHANGED
@@ -7,21 +7,20 @@ So that's what Propshaft doesn't do. Here's what it does provide:
7
7
  1. **Configurable load path**: You can register directories from multiple places in your app and gems, and reference assets from all of these paths as though they were one.
8
8
  1. **Digest stamping**: All assets in the load path will be copied (or compiled) in a precompilation step for production that also stamps all of them with a digest hash, so you can use long-expiry cache headers for better performance. The digested assets can be referred to through their logical path because the processing leaves a manifest file that provides a way to translate.
9
9
  1. **Development server**: There's no need to precompile the assets in development. You can refer to them via the same asset_path helpers and they'll be served by a development server.
10
- 1. **Basic compilers**: Propshaft was explicitly not designed to provide full transpiler capabilities. You can get that better elsewhere. But it does offer a simple input->output compiler setup that by default is used to translate `asset-path` function calls in CSS to `url(digested-asset)` instead.
10
+ 1. **Basic compilers**: Propshaft was explicitly not designed to provide full transpiler capabilities. You can get that better elsewhere. But it does offer a simple input->output compiler setup that by default is used to translate `url(asset)` function calls in CSS to `url(digested-asset)` instead and source mapping comments likewise.
11
11
 
12
12
 
13
13
  ## Installation
14
14
 
15
- With Rails 7+, you can start a new application with propshaft using `rails new myapp -a propshaft`.
16
-
15
+ With Rails 7+, you can start a new application with propshaft using `rails new myapp -a propshaft`. For existing applications, check the [upgrade guide](https://github.com/rails/propshaft/blob/main/UPGRADING.md) which contains step-by-step instructions.
17
16
 
18
17
  ## Usage
19
18
 
20
- Propshaft makes all the assets from all the paths it's been configured with through `config.assets.paths` available for serving and will copy all of them into `public/assets` when precompiling. This is unlike Sprockets, which did not copy over assets that hadn't been explicitly included in one of the bundled assets.
19
+ Propshaft makes all the assets from all the paths it's been configured with through `config.assets.paths` available for serving and will copy all of them into `public/assets` when precompiling. This is unlike Sprockets, which did not copy over assets that hadn't been explicitly included in one of the bundled assets.
21
20
 
22
- These assets can be referenced through their logical path using the normal helpers like `asset_path`, `image_tag`, `javascript_include_tag`, and all the other asset helper tags. These logical references are automatically converted into digest-aware paths in production when `assets:precompile` has been run (through a JSON mapping file found in `public/assets/.manifest.json`).
21
+ You can however exempt directories that have been added through the `config.assets.excluded_paths`. This is useful if you're for example using `app/assets/stylesheets` exclusively as a set of inputs to a compiler like Dart Sass for Rails, and you don't want these input files to be part of the load path. (Remember you need to add full paths, like `Rails.root.join("app/assets/stylesheets")`).
23
22
 
24
- Additionally, Propshaft ships with a CSS function called `asset-path("image.svg")` that'll be compiled into `url("/assets/image-f2e1ec14d6856e1958083094170ca6119c529a73.svg")` when doing `assets:precompile`. This function is applied to all `.css` files.
23
+ These assets can be referenced through their logical path using the normal helpers like `asset_path`, `image_tag`, `javascript_include_tag`, and all the other asset helper tags. These logical references are automatically converted into digest-aware paths in production when `assets:precompile` has been run (through a JSON mapping file found in `public/assets/.manifest.json`).
25
24
 
26
25
 
27
26
  ## Bypassing the digest step
@@ -15,7 +15,7 @@ class Propshaft::Assembly
15
15
  end
16
16
 
17
17
  def load_path
18
- @load_path ||= Propshaft::LoadPath.new(config.paths)
18
+ @load_path ||= Propshaft::LoadPath.new(config.paths, version: config.version)
19
19
  end
20
20
 
21
21
  def resolver
@@ -47,8 +47,8 @@ class Propshaft::Assembly
47
47
  def reveal(path_type = :logical_path)
48
48
  path_type = path_type.presence_in(%i[ logical_path path ]) || raise(ArgumentError, "Unknown path_type: #{path_type}")
49
49
 
50
- load_path.assets.each do |asset|
51
- Propshaft.logger.info asset.send(path_type)
50
+ load_path.assets.collect do |asset|
51
+ asset.send(path_type)
52
52
  end
53
53
  end
54
54
 
@@ -2,10 +2,10 @@ require "digest/sha1"
2
2
  require "action_dispatch/http/mime_type"
3
3
 
4
4
  class Propshaft::Asset
5
- attr_reader :path, :logical_path
5
+ attr_reader :path, :logical_path, :version
6
6
 
7
- def initialize(path, logical_path:)
8
- @path, @logical_path = path, Pathname.new(logical_path)
7
+ def initialize(path, logical_path:, version: nil)
8
+ @path, @logical_path, @version = path, Pathname.new(logical_path), version
9
9
  end
10
10
 
11
11
  def content
@@ -21,7 +21,7 @@ class Propshaft::Asset
21
21
  end
22
22
 
23
23
  def digest
24
- @digest ||= Digest::SHA1.hexdigest(content)
24
+ @digest ||= Digest::SHA1.hexdigest("#{content}#{version}")
25
25
  end
26
26
 
27
27
  def digested_path
@@ -1,10 +1,9 @@
1
1
  # frozen_string_literal: true
2
- require "propshaft/errors"
3
2
 
4
3
  class Propshaft::Compilers::CssAssetUrls
5
4
  attr_reader :assembly
6
5
 
7
- ASSET_URL_PATTERN = /url\(\s*["']?(?!(?:\#|data|http))([^"'\s)]+)\s*["']?\)/
6
+ ASSET_URL_PATTERN = /url\(\s*["']?(?!(?:\#|data|http))([^"'\s?#)]+)([#?][^"']+)?\s*["']?\)/
8
7
 
9
8
  def initialize(assembly)
10
9
  @assembly = assembly
@@ -1,5 +1,7 @@
1
- module Propshaft::Helper
2
- def compute_asset_path(path, options = {})
3
- Rails.application.assets.resolver.resolve(path)
1
+ module Propshaft
2
+ module Helper
3
+ def compute_asset_path(path, options = {})
4
+ Rails.application.assets.resolver.resolve(path) || raise(MissingAssetError.new(path))
5
+ end
4
6
  end
5
7
  end
@@ -1,10 +1,11 @@
1
1
  require "propshaft/asset"
2
2
 
3
3
  class Propshaft::LoadPath
4
- attr_reader :paths
4
+ attr_reader :paths, :version
5
5
 
6
- def initialize(paths = [])
7
- @paths = Array(paths).collect { |path| Pathname.new(path) }
6
+ def initialize(paths = [], version: nil)
7
+ @paths = dedup(paths)
8
+ @version = version
8
9
  end
9
10
 
10
11
  def find(asset_name)
@@ -45,9 +46,9 @@ class Propshaft::LoadPath
45
46
  def assets_by_path
46
47
  @cached_assets_by_path ||= Hash.new.tap do |mapped|
47
48
  paths.each do |path|
48
- all_files_from_tree(path).each do |file|
49
+ without_dotfiles(all_files_from_tree(path)).each do |file|
49
50
  logical_path = file.relative_path_from(path)
50
- mapped[logical_path.to_s] ||= Propshaft::Asset.new(file, logical_path: logical_path)
51
+ mapped[logical_path.to_s] ||= Propshaft::Asset.new(file, logical_path: logical_path, version: version)
51
52
  end if path.exist?
52
53
  end
53
54
  end
@@ -57,7 +58,19 @@ class Propshaft::LoadPath
57
58
  path.children.flat_map { |child| child.directory? ? all_files_from_tree(child) : child }
58
59
  end
59
60
 
61
+ def without_dotfiles(files)
62
+ files.reject { |file| file.basename.to_s.starts_with?(".") }
63
+ end
64
+
60
65
  def clear_cache
61
66
  @cached_assets_by_path = nil
62
67
  end
68
+
69
+ def dedup(paths)
70
+ [].tap do |deduped|
71
+ Array(paths).map(&:to_s).sort.each do |path|
72
+ deduped << Pathname.new(path) if deduped.blank? || !path.start_with?(deduped.last.to_s)
73
+ end
74
+ end
75
+ end
63
76
  end
@@ -4,9 +4,11 @@ require "active_support/ordered_options"
4
4
  module Propshaft
5
5
  class Railtie < ::Rails::Railtie
6
6
  config.assets = ActiveSupport::OrderedOptions.new
7
- config.assets.paths = []
8
- config.assets.prefix = "/assets"
9
- config.assets.compilers = [
7
+ config.assets.paths = []
8
+ config.assets.excluded_paths = []
9
+ config.assets.version = "1"
10
+ config.assets.prefix = "/assets"
11
+ config.assets.compilers = [
10
12
  [ "text/css", Propshaft::Compilers::CssAssetUrls ],
11
13
  [ "text/css", Propshaft::Compilers::SourceMappingUrls ],
12
14
  [ "text/javascript", Propshaft::Compilers::SourceMappingUrls ]
@@ -21,6 +23,8 @@ module Propshaft
21
23
  app.config.assets.paths.unshift(*paths["vendor/assets"].existent_directories)
22
24
  app.config.assets.paths.unshift(*paths["lib/assets"].existent_directories)
23
25
  app.config.assets.paths.unshift(*paths["app/assets"].existent_directories)
26
+
27
+ app.config.assets.paths = app.config.assets.paths.without(Array(app.config.assets.excluded_paths).collect(&:to_s))
24
28
  end
25
29
 
26
30
  config.after_initialize do |app|
@@ -16,13 +16,13 @@ namespace :assets do
16
16
 
17
17
  desc "Print all the assets available in config.assets.paths"
18
18
  task reveal: :environment do
19
- Rails.application.assets.reveal(:logical_path)
19
+ puts Rails.application.assets.reveal(:logical_path).join("\n")
20
20
  end
21
21
 
22
22
  namespace :reveal do
23
23
  desc "Print the full path of assets available in config.assets.paths"
24
24
  task full: :environment do
25
- Rails.application.assets.reveal(:path)
25
+ puts Rails.application.assets.reveal(:path).join("\n")
26
26
  end
27
27
  end
28
28
  end
@@ -9,8 +9,12 @@ module Propshaft::Resolver
9
9
  def resolve(logical_path)
10
10
  if asset = load_path.find(logical_path)
11
11
  File.join prefix, asset.digested_path
12
- else
13
- raise Propshaft::MissingAssetError.new(logical_path)
12
+ end
13
+ end
14
+
15
+ def read(logical_path)
16
+ if asset = load_path.find(logical_path)
17
+ asset.content
14
18
  end
15
19
  end
16
20
  end
@@ -9,8 +9,12 @@ module Propshaft::Resolver
9
9
  def resolve(logical_path)
10
10
  if asset_path = parsed_manifest[logical_path]
11
11
  File.join prefix, asset_path
12
- else
13
- raise Propshaft::MissingAssetError.new(logical_path)
12
+ end
13
+ end
14
+
15
+ def read(logical_path)
16
+ if asset_path = parsed_manifest[logical_path]
17
+ manifest_path.dirname.join(asset_path).read
14
18
  end
15
19
  end
16
20
 
@@ -1,3 +1,3 @@
1
1
  module Propshaft
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.3"
3
3
  end
data/lib/propshaft.rb CHANGED
@@ -7,5 +7,6 @@ module Propshaft
7
7
  end
8
8
 
9
9
  require "propshaft/assembly"
10
+ require "propshaft/errors"
10
11
  require "propshaft/helper"
11
12
  require "propshaft/railtie"
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.5.0
4
+ version: 0.6.3
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: 2022-01-27 00:00:00.000000000 Z
11
+ date: 2022-02-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack