darkroom 0.0.9 → 0.0.10
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 +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +175 -131
- data/VERSION +1 -1
- data/lib/darkroom/asset.rb +173 -151
- data/lib/darkroom/darkroom.rb +140 -124
- data/lib/darkroom/delegate.rb +208 -101
- data/lib/darkroom/delegates/{css.rb → css_delegate.rb} +1 -0
- data/lib/darkroom/delegates/{html.rb → html_delegate.rb} +4 -3
- data/lib/darkroom/delegates/{htx.rb → htx_delegate.rb} +3 -2
- data/lib/darkroom/delegates/{javascript.rb → javascript_delegate.rb} +9 -8
- data/lib/darkroom/errors/asset_error.rb +6 -17
- data/lib/darkroom/errors/asset_not_found_error.rb +4 -8
- data/lib/darkroom/errors/circular_reference_error.rb +4 -8
- data/lib/darkroom/errors/duplicate_asset_error.rb +7 -16
- data/lib/darkroom/errors/invalid_path_error.rb +5 -14
- data/lib/darkroom/errors/missing_library_error.rb +7 -16
- data/lib/darkroom/errors/processing_error.rb +13 -20
- data/lib/darkroom/errors/unrecognized_extension_error.rb +4 -8
- data/lib/darkroom/version.rb +1 -1
- data/lib/darkroom.rb +4 -6
- metadata +17 -21
    
        data/lib/darkroom/darkroom.rb
    CHANGED
    
    | @@ -3,17 +3,16 @@ | |
| 3 3 | 
             
            require('set')
         | 
| 4 4 |  | 
| 5 5 | 
             
            require_relative('asset')
         | 
| 6 | 
            +
            require_relative('delegate')
         | 
| 6 7 | 
             
            require_relative('errors/asset_not_found_error')
         | 
| 7 8 | 
             
            require_relative('errors/duplicate_asset_error')
         | 
| 8 9 | 
             
            require_relative('errors/invalid_path_error')
         | 
| 9 10 | 
             
            require_relative('errors/processing_error')
         | 
| 10 11 |  | 
| 11 | 
            -
             | 
| 12 | 
            -
            # Main class providing fast, lightweight, and straightforward web asset management.
         | 
| 13 | 
            -
            #
         | 
| 12 | 
            +
            # Main class providing simple and straightforward web asset management.
         | 
| 14 13 | 
             
            class Darkroom
         | 
| 15 14 | 
             
              DEFAULT_MINIFIED = /(\.|-)min\.\w+$/.freeze
         | 
| 16 | 
            -
              TRAILING_SLASHES =  | 
| 15 | 
            +
              TRAILING_SLASHES = %r{/+$}.freeze
         | 
| 17 16 | 
             
              PRISTINE = Set.new(%w[/favicon.ico /mask-icon.svg /humans.txt /robots.txt]).freeze
         | 
| 18 17 | 
             
              MIN_PROCESS_INTERVAL = 0.5
         | 
| 19 18 |  | 
| @@ -24,25 +23,36 @@ class Darkroom | |
| 24 23 |  | 
| 25 24 | 
             
              class << self; attr_accessor(:javascript_iife) end
         | 
| 26 25 |  | 
| 27 | 
            -
               | 
| 28 | 
            -
              # Registers an asset delegate.
         | 
| 26 | 
            +
              # Public: Register a delegate for handling a specific kind of asset.
         | 
| 29 27 | 
             
              #
         | 
| 30 | 
            -
              #  | 
| 31 | 
            -
              #  | 
| 28 | 
            +
              # args  - One or more String file extensions to associate with this delegate, optionally followed by
         | 
| 29 | 
            +
              #         either an HTTP MIME type String or a Delegate subclass.
         | 
| 30 | 
            +
              # block - Block to call that defines or extends the Delegate.
         | 
| 32 31 | 
             
              #
         | 
| 33 | 
            -
               | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 32 | 
            +
              # Examples
         | 
| 33 | 
            +
              #
         | 
| 34 | 
            +
              #   Darkroom.register('.ext1', '.ext2', 'content/type')
         | 
| 35 | 
            +
              #   Darkroom.register('.ext', MyDelegateSubclass)
         | 
| 36 | 
            +
              #
         | 
| 37 | 
            +
              #   Darkroom.register('.scss', 'text/css') do
         | 
| 38 | 
            +
              #     compile(lib: 'sassc') { ... }
         | 
| 39 | 
            +
              #   end
         | 
| 40 | 
            +
              #
         | 
| 41 | 
            +
              #   Darkroom.register('.scss', SCSSDelegate) do
         | 
| 42 | 
            +
              #     # Modifications/overrides of the SCSSDelegate class...
         | 
| 43 | 
            +
              #   end
         | 
| 44 | 
            +
              #
         | 
| 45 | 
            +
              # Returns the Delegate class.
         | 
| 46 | 
            +
              def self.register(*args, &block)
         | 
| 47 | 
            +
                last_arg = args.pop unless args.last.kind_of?(String) && args.last[0] == '.'
         | 
| 48 | 
            +
                extensions = args
         | 
| 41 49 |  | 
| 50 | 
            +
                if last_arg.nil? || last_arg.kind_of?(String)
         | 
| 51 | 
            +
                  content_type = last_arg
         | 
| 42 52 | 
             
                  delegate = Class.new(Delegate, &block)
         | 
| 43 53 | 
             
                  delegate.content_type(content_type) if content_type && !delegate.content_type
         | 
| 44 | 
            -
                elsif  | 
| 45 | 
            -
                  delegate = block ? Class.new( | 
| 54 | 
            +
                elsif last_arg.kind_of?(Class) && last_arg < Delegate
         | 
| 55 | 
            +
                  delegate = block ? Class.new(last_arg, &block) : last_arg
         | 
| 46 56 | 
             
                end
         | 
| 47 57 |  | 
| 48 58 | 
             
                extensions.each do |extension|
         | 
| @@ -54,45 +64,38 @@ class Darkroom | |
| 54 64 | 
             
                delegate
         | 
| 55 65 | 
             
              end
         | 
| 56 66 |  | 
| 57 | 
            -
               | 
| 58 | 
            -
              # Returns the delegate associated with a file extension.
         | 
| 67 | 
            +
              # Public: Get the Delegate associated with a file extension.
         | 
| 59 68 | 
             
              #
         | 
| 60 | 
            -
              #  | 
| 69 | 
            +
              # extension - String file extension of the desired delegate (e.g. '.js')
         | 
| 61 70 | 
             
              #
         | 
| 71 | 
            +
              # Returns the Delegate class.
         | 
| 62 72 | 
             
              def self.delegate(extension)
         | 
| 63 73 | 
             
                @@delegates[extension]
         | 
| 64 74 | 
             
              end
         | 
| 65 75 |  | 
| 66 | 
            -
               | 
| 67 | 
            -
              # Utility method that prints a warning with file and line number of a deprecated call.
         | 
| 68 | 
            -
              #
         | 
| 69 | 
            -
              def self.deprecated(message)
         | 
| 70 | 
            -
                location = caller_locations(2, 1).first
         | 
| 71 | 
            -
             | 
| 72 | 
            -
                warn("#{location.path}:#{location.lineno}: #{message}")
         | 
| 73 | 
            -
              end
         | 
| 74 | 
            -
             | 
| 75 | 
            -
              ##
         | 
| 76 | 
            -
              # Creates a new instance.
         | 
| 77 | 
            -
              #
         | 
| 78 | 
            -
              # [*load_paths] One or more paths where assets are located on disk.
         | 
| 79 | 
            -
              # [host:] Host(s) to prepend to paths (useful when serving from a CDN in production). If multiple hosts
         | 
| 80 | 
            -
              #         are specified, they will be round-robined within each thread for each call to +#asset_path+.
         | 
| 81 | 
            -
              # [hosts:] Alias of +host:+.
         | 
| 82 | 
            -
              # [prefix:] Prefix to prepend to asset paths (e.g. +/assets+).
         | 
| 83 | 
            -
              # [pristine:] Path(s) that should not include prefix and for which unversioned form should be provided by
         | 
| 84 | 
            -
              #             default (e.g. +/favicon.ico+).
         | 
| 85 | 
            -
              # [entries:] String, regex, or array of strings and regexes specifying entry point paths / path patterns.
         | 
| 86 | 
            -
              # [minify:] Boolean specifying whether or not to minify assets.
         | 
| 87 | 
            -
              # [minified:] String, regex, or array of strings and regexes specifying paths of assets that are already
         | 
| 88 | 
            -
              #             minified and thus should be skipped for minification.
         | 
| 89 | 
            -
              # [min_process_interval:] Minimum time required between one run of asset processing and another.
         | 
| 76 | 
            +
              # Public: Create a new instance.
         | 
| 90 77 | 
             
              #
         | 
| 78 | 
            +
              # load_paths            - One or more String paths where assets are located on disk.
         | 
| 79 | 
            +
              # host:                 - String host or Array of String hosts to prepend to paths (useful when serving
         | 
| 80 | 
            +
              #                         from a CDN in production). If multiple hosts are specified, they will be round-
         | 
| 81 | 
            +
              #                         robined within each thread for each call to #asset_path.
         | 
| 82 | 
            +
              # hosts:                - String or Array of Strings (alias of host:).
         | 
| 83 | 
            +
              # prefix:               - String prefix to prepend to asset paths (e.g. '/assets').
         | 
| 84 | 
            +
              # pristine:             - String, Array of String, or Set of String paths that should not include the
         | 
| 85 | 
            +
              #                         prefix and for which the unversioned form should be provided by default (e.g.
         | 
| 86 | 
            +
              #                         '/favicon.ico').
         | 
| 87 | 
            +
              # entries:              - String, Regexp, or Array of String and/or Regexp specifying entry point paths /
         | 
| 88 | 
            +
              #                         path patterns.
         | 
| 89 | 
            +
              # minify:               - Boolean specifying if assets that support it should be minified.
         | 
| 90 | 
            +
              # minified:             - String, Regexp, or Array of String and/or Regexp specifying paths of assets that
         | 
| 91 | 
            +
              #                         are already minified and thus shouldn't be minified.
         | 
| 92 | 
            +
              # min_process_interval: - Numeric minimum number of seconds required between one run of asset processing
         | 
| 93 | 
            +
              #                         and another.
         | 
| 91 94 | 
             
              def initialize(*load_paths, host: nil, hosts: nil, prefix: nil, pristine: nil, entries: nil,
         | 
| 92 | 
            -
             | 
| 95 | 
            +
                             minify: false, minified: DEFAULT_MINIFIED, min_process_interval: MIN_PROCESS_INTERVAL)
         | 
| 93 96 | 
             
                @load_paths = load_paths.map { |load_path| File.expand_path(load_path) }
         | 
| 94 97 |  | 
| 95 | 
            -
                @hosts = (Array(host) + Array(hosts)).map! { | | 
| 98 | 
            +
                @hosts = (Array(host) + Array(hosts)).map! { |h| h.sub(TRAILING_SLASHES, '') }
         | 
| 96 99 | 
             
                @entries = Array(entries)
         | 
| 97 100 | 
             
                @minify = minify
         | 
| 98 101 | 
             
                @minified = Array(minified)
         | 
| @@ -116,16 +119,24 @@ class Darkroom | |
| 116 119 | 
             
                Thread.current[:darkroom_host_index] = -1 unless @hosts.empty?
         | 
| 117 120 | 
             
              end
         | 
| 118 121 |  | 
| 119 | 
            -
               | 
| 120 | 
            -
              #  | 
| 121 | 
            -
              #  | 
| 122 | 
            -
              # | 
| 122 | 
            +
              # Public: Walk all load paths and refresh any assets that have been modified on disk since the last call
         | 
| 123 | 
            +
              # to this method. Processing is skipped if either a) a previous call to this method happened
         | 
| 124 | 
            +
              # less than min_process_interval seconds ago or b) another thread is currently executing this method.
         | 
| 125 | 
            +
              #
         | 
| 126 | 
            +
              # A mutex is used to ensure that, say, multiple web request threads do not trample each other. If the
         | 
| 127 | 
            +
              # mutex is locked when this method is called, it will wait until the mutex is released to ensure that the
         | 
| 128 | 
            +
              # caller does not then start working with stale / invalid Asset objects due to the work of the other
         | 
| 129 | 
            +
              # thread's active call to #process being incomplete.
         | 
| 123 130 | 
             
              #
         | 
| 131 | 
            +
              # If any errors are encountered during processing, they must be checked for manually afterward via #error
         | 
| 132 | 
            +
              # or #errors. If a raise is preferred, use #process! instead.
         | 
| 133 | 
            +
              #
         | 
| 134 | 
            +
              # Returns boolean indicating if processing actually happened (true) or was skipped (false).
         | 
| 124 135 | 
             
              def process
         | 
| 125 136 | 
             
                return false if Time.now.to_f - @last_processed_at < @min_process_interval
         | 
| 126 137 |  | 
| 127 138 | 
             
                if @mutex.locked?
         | 
| 128 | 
            -
                  @mutex.synchronize {}
         | 
| 139 | 
            +
                  @mutex.synchronize {} # Wait until other #process call is done to avoid stale/invalid assets.
         | 
| 129 140 | 
             
                  return false
         | 
| 130 141 | 
             
                end
         | 
| 131 142 |  | 
| @@ -135,10 +146,10 @@ class Darkroom | |
| 135 146 | 
             
                  found = {}
         | 
| 136 147 |  | 
| 137 148 | 
             
                  @load_paths.each do |load_path|
         | 
| 138 | 
            -
                    Dir.glob(File.join(load_path, @@glob)). | 
| 149 | 
            +
                    Dir.glob(File.join(load_path, @@glob)).each do |file|
         | 
| 139 150 | 
             
                      path = file.sub(load_path, '')
         | 
| 140 151 |  | 
| 141 | 
            -
                      if index = ( | 
| 152 | 
            +
                      if (index = path.index(Asset::INVALID_PATH_REGEX))
         | 
| 142 153 | 
             
                        @errors << InvalidPathError.new(path, index)
         | 
| 143 154 | 
             
                      elsif found.key?(path)
         | 
| 144 155 | 
             
                        @errors << DuplicateAssetError.new(path, found[path], load_path)
         | 
| @@ -148,7 +159,8 @@ class Darkroom | |
| 148 159 | 
             
                        unless @manifest.key?(path)
         | 
| 149 160 | 
             
                          entry = entry?(path)
         | 
| 150 161 |  | 
| 151 | 
            -
                          @manifest[path] = Asset.new( | 
| 162 | 
            +
                          @manifest[path] = Asset.new(
         | 
| 163 | 
            +
                            path, file, self,
         | 
| 152 164 | 
             
                            prefix: (@prefix unless @pristine.include?(path)),
         | 
| 153 165 | 
             
                            entry: entry,
         | 
| 154 166 | 
             
                            minify: entry && @minify && !minified?(path),
         | 
| @@ -162,7 +174,7 @@ class Darkroom | |
| 162 174 | 
             
                  @manifest_unversioned.clear
         | 
| 163 175 | 
             
                  @manifest_versioned.clear
         | 
| 164 176 |  | 
| 165 | 
            -
                  @manifest. | 
| 177 | 
            +
                  @manifest.each_value do |asset|
         | 
| 166 178 | 
             
                    asset.process
         | 
| 167 179 |  | 
| 168 180 | 
             
                    if asset.entry?
         | 
| @@ -180,94 +192,102 @@ class Darkroom | |
| 180 192 | 
             
                end
         | 
| 181 193 | 
             
              end
         | 
| 182 194 |  | 
| 183 | 
            -
               | 
| 184 | 
            -
              # Calls #process. If processing was skipped, returns false. If processing was performed, raises an
         | 
| 185 | 
            -
              # exception if any errors were encountered and returns true otherwise.
         | 
| 195 | 
            +
              # Public: Call #process but raise an error if there were errors.
         | 
| 186 196 | 
             
              #
         | 
| 197 | 
            +
              # Returns boolean indicating if processing actually happened (true) or was skipped (false).
         | 
| 198 | 
            +
              # Raises ProcessingError if processing actually happened from this call and error(s) were encountered.
         | 
| 187 199 | 
             
              def process!
         | 
| 188 200 | 
             
                result = process
         | 
| 189 201 |  | 
| 190 | 
            -
                 | 
| 202 | 
            +
                result && @error ? raise(@error) : result
         | 
| 191 203 | 
             
              end
         | 
| 192 204 |  | 
| 193 | 
            -
               | 
| 194 | 
            -
              # Returns boolean indicating whether or not there were any errors encountered the last time assets were
         | 
| 195 | 
            -
              # processed.
         | 
| 205 | 
            +
              # Public: Check if there were any errors encountered the last time assets were processed.
         | 
| 196 206 | 
             
              #
         | 
| 207 | 
            +
              # Returns the boolean result.
         | 
| 197 208 | 
             
              def error?
         | 
| 198 209 | 
             
                !!@error
         | 
| 199 210 | 
             
              end
         | 
| 200 211 |  | 
| 201 | 
            -
               | 
| 202 | 
            -
              #  | 
| 203 | 
            -
              # | 
| 204 | 
            -
              #  | 
| 212 | 
            +
              # Public: Get an Asset object, given its external path. An external path includes any prefix and can be
         | 
| 213 | 
            +
              # either the versioned or unversioned form (i.e. how an HTTP request for the asset comes in).
         | 
| 214 | 
            +
              #
         | 
| 215 | 
            +
              # Examples
         | 
| 205 216 | 
             
              #
         | 
| 206 | 
            -
              #    | 
| 207 | 
            -
              #   darkroom.asset('/assets/js/app | 
| 217 | 
            +
              #   # Suppose the asset's internal path is '/js/app.js' and the prefix is '/assets'.
         | 
| 218 | 
            +
              #   darkroom.asset('/assets/js/app-<hash>.js') # => #<Darkroom::Asset [...]>
         | 
| 219 | 
            +
              #   darkroom.asset('/assets/js/app.js')        # => #<Darkroom::Asset [...]>
         | 
| 208 220 | 
             
              #
         | 
| 209 | 
            -
              #  | 
| 221 | 
            +
              # path - String external path of the asset.
         | 
| 210 222 | 
             
              #
         | 
| 223 | 
            +
              # Returns the Asset object if it exists or nil otherwise.
         | 
| 211 224 | 
             
              def asset(path)
         | 
| 212 225 | 
             
                @manifest_versioned[path] || @manifest_unversioned[path]
         | 
| 213 226 | 
             
              end
         | 
| 214 227 |  | 
| 215 | 
            -
               | 
| 216 | 
            -
              #  | 
| 217 | 
            -
              # can be either the versioned or unversioned form of the asset path (i.e. how an HTTP request for the
         | 
| 218 | 
            -
              # asset comes in). For example, to get the external path for the Asset object with path +/js/app.js+ when
         | 
| 219 | 
            -
              # prefix is +/assets+:
         | 
| 228 | 
            +
              # Public: Get the external asset path, given its internal path. An external path includes any prefix and
         | 
| 229 | 
            +
              # can be either the versioned or unversioned form (i.e. how an HTTP request for the asset comes in).
         | 
| 220 230 | 
             
              #
         | 
| 221 | 
            -
              # | 
| 222 | 
            -
              # | 
| 231 | 
            +
              # path       - String internal path of the asset.
         | 
| 232 | 
            +
              # versioned: - Boolean specifying either the versioned or unversioned path to be returned.
         | 
| 223 233 | 
             
              #
         | 
| 224 | 
            -
              #  | 
| 234 | 
            +
              # Examples
         | 
| 225 235 | 
             
              #
         | 
| 226 | 
            -
              #  | 
| 227 | 
            -
              #  | 
| 236 | 
            +
              #   # Suppose the asset's internal path is '/js/app.js' and the prefix is '/assets'.
         | 
| 237 | 
            +
              #   darkroom.asset_path('/js/app.js')                   # => "/assets/js/app-<hash>.js"
         | 
| 238 | 
            +
              #   darkroom.asset_path('/js/app.js', versioned: false) # => "/assets/js/app.js"
         | 
| 228 239 | 
             
              #
         | 
| 240 | 
            +
              # Returns the String external asset path.
         | 
| 241 | 
            +
              # Raises AssetNotFoundError if the asset doesn't exist.
         | 
| 229 242 | 
             
              def asset_path(path, versioned: !@pristine.include?(path))
         | 
| 230 243 | 
             
                asset = @manifest[path] or raise(AssetNotFoundError.new(path))
         | 
| 231 | 
            -
             | 
| 232 | 
            -
             | 
| 233 | 
            -
             | 
| 244 | 
            +
             | 
| 245 | 
            +
                unless @hosts.empty?
         | 
| 246 | 
            +
                  host_index = (Thread.current[:darkroom_host_index] + 1) % @hosts.size
         | 
| 247 | 
            +
                  host = @hosts[host_index]
         | 
| 248 | 
            +
             | 
| 249 | 
            +
                  Thread.current[:darkroom_host_index] = host_index
         | 
| 250 | 
            +
                end
         | 
| 234 251 |  | 
| 235 252 | 
             
                "#{host}#{versioned ? asset.path_versioned : asset.path_unversioned}"
         | 
| 236 253 | 
             
              end
         | 
| 237 254 |  | 
| 238 | 
            -
               | 
| 239 | 
            -
              # Returns an asset's subresource integrity string. Raises an AssetNotFoundError if the asset doesn't
         | 
| 240 | 
            -
              # exist.
         | 
| 255 | 
            +
              # Public: Get an asset's subresource integrity string.
         | 
| 241 256 | 
             
              #
         | 
| 242 | 
            -
              #  | 
| 243 | 
            -
              #  | 
| 257 | 
            +
              # path      - String internal path of the asset.
         | 
| 258 | 
            +
              # algorithm - Symbol hash algorithm name to use to generate the integrity string (must be one of
         | 
| 259 | 
            +
              #             :sha256, :sha384, :sha512).
         | 
| 244 260 | 
             
              #
         | 
| 261 | 
            +
              # Returns the asset's subresource integrity String.
         | 
| 262 | 
            +
              # Raises AssetNotFoundError if the asset doesn't exist.
         | 
| 245 263 | 
             
              def asset_integrity(path, algorithm = nil)
         | 
| 246 264 | 
             
                asset = @manifest[path] or raise(AssetNotFoundError.new(path))
         | 
| 247 265 |  | 
| 248 266 | 
             
                algorithm ? asset.integrity(algorithm) : asset.integrity
         | 
| 249 267 | 
             
              end
         | 
| 250 268 |  | 
| 251 | 
            -
               | 
| 252 | 
            -
              # Returns the asset from the manifest hash associated with the given path.
         | 
| 269 | 
            +
              # Public: Get the Asset object from the manifest Hash associated with the given path.
         | 
| 253 270 | 
             
              #
         | 
| 254 | 
            -
              #  | 
| 271 | 
            +
              # path - String internal path of the asset.
         | 
| 255 272 | 
             
              #
         | 
| 273 | 
            +
              # Returns the Asset object if it exists or nil otherwise.
         | 
| 256 274 | 
             
              def manifest(path)
         | 
| 257 275 | 
             
                @manifest[path]
         | 
| 258 276 | 
             
              end
         | 
| 259 277 |  | 
| 260 | 
            -
               | 
| 261 | 
            -
              #  | 
| 262 | 
            -
              #  | 
| 278 | 
            +
              # Public: Write assets to disk. This is useful when deploying to a production environment where assets
         | 
| 279 | 
            +
              # will be uploaded to and served from a CDN or proxy server. Note that #process must be called manually
         | 
| 280 | 
            +
              # before calling this method.
         | 
| 263 281 | 
             
              #
         | 
| 264 | 
            -
              #  | 
| 265 | 
            -
              #  | 
| 266 | 
            -
              # | 
| 267 | 
            -
              #  | 
| 282 | 
            +
              # dir               - String directory path to write the assets to.
         | 
| 283 | 
            +
              # clear:            - Boolean indicating if the existing contents of the directory should be deleted
         | 
| 284 | 
            +
              #                     before writing files.
         | 
| 285 | 
            +
              # include_pristine: - Boolean indicating if pristine assets should be included (when dumping for the
         | 
| 268 286 | 
             
              #                     purpose of uploading to a CDN, assets such as /robots.txt and /favicon.ico don't
         | 
| 269 287 | 
             
              #                     need to be included).
         | 
| 270 288 | 
             
              #
         | 
| 289 | 
            +
              # Returns nothing.
         | 
| 290 | 
            +
              # Raises ProcessingError if errors were encountered during the last #process run.
         | 
| 271 291 | 
             
              def dump(dir, clear: false, include_pristine: true)
         | 
| 272 292 | 
             
                raise(@error) if @error
         | 
| 273 293 |  | 
| @@ -281,45 +301,41 @@ class Darkroom | |
| 281 301 | 
             
                @manifest_versioned.each do |path, asset|
         | 
| 282 302 | 
             
                  next if @pristine.include?(asset.path) && !include_pristine
         | 
| 283 303 |  | 
| 284 | 
            -
                  file_path = File.join(dir,
         | 
| 285 | 
            -
                    @pristine.include?(asset.path) ? asset.path_unversioned : path
         | 
| 286 | 
            -
                  )
         | 
| 304 | 
            +
                  file_path = File.join(dir, @pristine.include?(asset.path) ? asset.path_unversioned : path)
         | 
| 287 305 |  | 
| 288 306 | 
             
                  FileUtils.mkdir_p(File.dirname(file_path))
         | 
| 289 307 | 
             
                  File.write(file_path, asset.content)
         | 
| 290 308 | 
             
                end
         | 
| 291 309 | 
             
              end
         | 
| 292 310 |  | 
| 293 | 
            -
               | 
| 294 | 
            -
              # Returns high-level object info string.
         | 
| 311 | 
            +
              # Public: Get a high-level object info string about this Darkroom instance.
         | 
| 295 312 | 
             
              #
         | 
| 313 | 
            +
              # Returns the String.
         | 
| 296 314 | 
             
              def inspect
         | 
| 297 | 
            -
                "#<#{self.class} "\
         | 
| 298 | 
            -
                  "@entries=#{@entries.inspect}, "\
         | 
| 299 | 
            -
                  "@errors=#{@errors.inspect}, "\
         | 
| 300 | 
            -
                  "@hosts=#{@hosts.inspect}, "\
         | 
| 301 | 
            -
                  "@last_processed_at=#{@last_processed_at.inspect}, "\
         | 
| 302 | 
            -
                  "@load_paths=#{@load_paths.inspect}, "\
         | 
| 303 | 
            -
                  "@min_process_interval=#{@min_process_interval.inspect}, "\
         | 
| 304 | 
            -
                  "@minified=#{@minified.inspect}, "\
         | 
| 305 | 
            -
                  "@minify=#{@minify.inspect}, "\
         | 
| 306 | 
            -
                  "@prefix=#{@prefix.inspect}, "\
         | 
| 307 | 
            -
                  "@pristine=#{@pristine.inspect}, "\
         | 
| 308 | 
            -
                  "@process_key=#{@process_key.inspect}"\
         | 
| 315 | 
            +
                "#<#{self.class} " \
         | 
| 316 | 
            +
                  "@entries=#{@entries.inspect}, " \
         | 
| 317 | 
            +
                  "@errors=#{@errors.inspect}, " \
         | 
| 318 | 
            +
                  "@hosts=#{@hosts.inspect}, " \
         | 
| 319 | 
            +
                  "@last_processed_at=#{@last_processed_at.inspect}, " \
         | 
| 320 | 
            +
                  "@load_paths=#{@load_paths.inspect}, " \
         | 
| 321 | 
            +
                  "@min_process_interval=#{@min_process_interval.inspect}, " \
         | 
| 322 | 
            +
                  "@minified=#{@minified.inspect}, " \
         | 
| 323 | 
            +
                  "@minify=#{@minify.inspect}, " \
         | 
| 324 | 
            +
                  "@prefix=#{@prefix.inspect}, " \
         | 
| 325 | 
            +
                  "@pristine=#{@pristine.inspect}, " \
         | 
| 326 | 
            +
                  "@process_key=#{@process_key.inspect}" \
         | 
| 309 327 | 
             
                '>'
         | 
| 310 328 | 
             
              end
         | 
| 311 329 |  | 
| 312 330 | 
             
              private
         | 
| 313 331 |  | 
| 314 | 
            -
               | 
| 315 | 
            -
              # Returns boolean indicating whether or not the provided path is an entry point.
         | 
| 332 | 
            +
              # Internal: Check if an asset's path indicates that it's an entry point.
         | 
| 316 333 | 
             
              #
         | 
| 317 | 
            -
              #  | 
| 334 | 
            +
              # path - String asset path to check.
         | 
| 318 335 | 
             
              #
         | 
| 336 | 
            +
              # Returns the boolean result.
         | 
| 319 337 | 
             
              def entry?(path)
         | 
| 320 | 
            -
                if @pristine.include?(path)
         | 
| 321 | 
            -
                  true
         | 
| 322 | 
            -
                elsif @entries.empty?
         | 
| 338 | 
            +
                if @pristine.include?(path) || @entries.empty?
         | 
| 323 339 | 
             
                  true
         | 
| 324 340 | 
             
                else
         | 
| 325 341 | 
             
                  @entries.any? do |entry|
         | 
| @@ -328,11 +344,11 @@ class Darkroom | |
| 328 344 | 
             
                end
         | 
| 329 345 | 
             
              end
         | 
| 330 346 |  | 
| 331 | 
            -
               | 
| 332 | 
            -
              # Returns boolean indicating whether or not the asset with the provided path is already minified.
         | 
| 347 | 
            +
              # Internal: Check if an asset's path indicates that it's already minified.
         | 
| 333 348 | 
             
              #
         | 
| 334 | 
            -
              #  | 
| 349 | 
            +
              # path - String asset path to check.
         | 
| 335 350 | 
             
              #
         | 
| 351 | 
            +
              # Returns the boolean result.
         | 
| 336 352 | 
             
              def minified?(path)
         | 
| 337 353 | 
             
                @minified.any? do |minified|
         | 
| 338 354 | 
             
                  path == minified || (minified.kind_of?(Regexp) && path.match?(minified))
         |