condenser 1.3 → 1.4
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/lib/condenser/asset.rb +52 -21
- data/lib/condenser/build_cache.rb +21 -8
- data/lib/condenser/helpers/parse_helpers.rb +7 -0
- data/lib/condenser/processors/babel_processor.rb +8 -14
- data/lib/condenser/processors/js_analyzer.rb +41 -6
- data/lib/condenser/processors/node_processor.rb +1 -0
- data/lib/condenser/processors/rollup_processor.rb +1 -1
- data/lib/condenser/resolve.rb +26 -3
- data/lib/condenser/version.rb +1 -1
- data/test/cache_test.rb +111 -16
- data/test/dependency_test.rb +51 -2
- data/test/preprocessor/babel_test.rb +65 -54
- data/test/preprocessor/js_analyzer_test.rb +35 -0
- data/test/resolve_test.rb +10 -0
- data/test/server_test.rb +9 -9
- data/test/test_helper.rb +6 -3
- metadata +3 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 171baa1e5cd8016c4b2e7f142147d174410085ede075c101da43b743a4ad6fec
         | 
| 4 | 
            +
              data.tar.gz: 9c97b58fb2bf540b335f6504997da99fac72891f61a0a0631639ae3fd9f28482
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: decc8b993d0e99c5212f3c0b1d4be88de43d49ab1386f32936a0dae482fc9b45de55cbbc51d99eafce58bcd68809a20fd27267ef0fe62d3aa3a244e33e68992e
         | 
| 7 | 
            +
              data.tar.gz: e39a90c28c7beab789885e53e35ae0ad43340ff4009f81ad1586ac16eb0073dbaf999b69a94f78e796f5bfe5e93a16e0a45481e76b706d0e496dfbe5435b4966
         | 
    
        data/lib/condenser/asset.rb
    CHANGED
    
    | @@ -65,33 +65,31 @@ class Condenser | |
| 65 65 | 
             
                def process_dependencies
         | 
| 66 66 | 
             
                  deps = @environment.cache.fetch "direct-deps/#{cache_key}" do
         | 
| 67 67 | 
             
                    process
         | 
| 68 | 
            -
                    @process_dependencies
         | 
| 68 | 
            +
                    @process_dependencies.map { |fn| [normalize_filename_base(fn[0]), fn[1]] }
         | 
| 69 69 | 
             
                  end
         | 
| 70 70 |  | 
| 71 | 
            -
                   | 
| 72 | 
            -
             | 
| 73 | 
            -
                    i = [i, @content_types] if i.is_a?(String)
         | 
| 71 | 
            +
                  deps.inject([]) do |memo, i|
         | 
| 72 | 
            +
                    i[0] = File.join(@environment.base, i[0].delete_prefix('!')) if i[0].start_with?('!') && @environment.base
         | 
| 74 73 | 
             
                    @environment.resolve(i[0], File.dirname(@source_file), accept: i[1]).each do |asset|
         | 
| 75 | 
            -
                       | 
| 74 | 
            +
                      memo << asset
         | 
| 76 75 | 
             
                    end
         | 
| 76 | 
            +
                    memo
         | 
| 77 77 | 
             
                  end
         | 
| 78 | 
            -
                  d
         | 
| 79 78 | 
             
                end
         | 
| 80 79 |  | 
| 81 80 | 
             
                def export_dependencies
         | 
| 82 81 | 
             
                  deps = @environment.cache.fetch "export-deps/#{cache_key}" do
         | 
| 83 82 | 
             
                    process
         | 
| 84 | 
            -
                    @export_dependencies + @process_dependencies
         | 
| 83 | 
            +
                    (@export_dependencies + @process_dependencies).map { |fn| [normalize_filename_base(fn[0]), fn[1]] }
         | 
| 85 84 | 
             
                  end
         | 
| 86 85 |  | 
| 87 | 
            -
                   | 
| 88 | 
            -
             | 
| 89 | 
            -
                    i = [i, @content_types] if i.is_a?(String)
         | 
| 86 | 
            +
                  deps.inject([]) do |memo, i|
         | 
| 87 | 
            +
                    i[0] = File.join(@environment.base, i[0].delete_prefix('!')) if i[0].start_with?('!') && @environment.base
         | 
| 90 88 | 
             
                    @environment.resolve(i[0], File.dirname(@source_file), accept: i[1]).each do |asset|
         | 
| 91 | 
            -
                       | 
| 89 | 
            +
                      memo << asset
         | 
| 92 90 | 
             
                    end
         | 
| 91 | 
            +
                    memo
         | 
| 93 92 | 
             
                  end
         | 
| 94 | 
            -
                  d
         | 
| 95 93 | 
             
                end
         | 
| 96 94 |  | 
| 97 95 | 
             
                def has_default_export?
         | 
| @@ -123,17 +121,27 @@ class Condenser | |
| 123 121 | 
             
                  end
         | 
| 124 122 | 
             
                end
         | 
| 125 123 |  | 
| 126 | 
            -
                def all_process_dependencies
         | 
| 127 | 
            -
                  f = [ | 
| 128 | 
            -
                   | 
| 124 | 
            +
                def all_process_dependencies(visited = Set.new)
         | 
| 125 | 
            +
                  f = []
         | 
| 126 | 
            +
                  if !visited.include?(@source_file)
         | 
| 127 | 
            +
                    f << @source_file
         | 
| 128 | 
            +
                    visited << self.source_file
         | 
| 129 | 
            +
                  end
         | 
| 130 | 
            +
                  
         | 
| 131 | 
            +
                  all_dependenies(process_dependencies, visited, :process_dependencies) do |dep|
         | 
| 129 132 | 
             
                    f << dep.source_file
         | 
| 130 133 | 
             
                  end
         | 
| 131 134 | 
             
                  f
         | 
| 132 135 | 
             
                end
         | 
| 133 136 |  | 
| 134 | 
            -
                def all_export_dependencies
         | 
| 135 | 
            -
                  f = [ | 
| 136 | 
            -
                   | 
| 137 | 
            +
                def all_export_dependencies(visited = Set.new)
         | 
| 138 | 
            +
                  f = []
         | 
| 139 | 
            +
                  if !visited.include?(@source_file)
         | 
| 140 | 
            +
                    f << @source_file
         | 
| 141 | 
            +
                    visited << self.source_file
         | 
| 142 | 
            +
                  end
         | 
| 143 | 
            +
                  
         | 
| 144 | 
            +
                  all_dependenies(export_dependencies, visited, :export_dependencies) do |dep|
         | 
| 137 145 | 
             
                    f << dep.source_file
         | 
| 138 146 | 
             
                  end
         | 
| 139 147 | 
             
                  f
         | 
| @@ -143,19 +151,29 @@ class Condenser | |
| 143 151 | 
             
                  @cache_key ||= Digest::SHA1.base64digest(JSON.generate([
         | 
| 144 152 | 
             
                    Condenser::VERSION,
         | 
| 145 153 | 
             
                    @environment.pipline_digest,
         | 
| 146 | 
            -
                    @ | 
| 154 | 
            +
                    normalize_filename_base(@source_file),
         | 
| 147 155 | 
             
                    Digest::SHA256.file(@source_file).hexdigest,
         | 
| 148 156 | 
             
                    @content_types_digest
         | 
| 149 157 | 
             
                  ]))
         | 
| 150 158 | 
             
                end
         | 
| 151 159 |  | 
| 160 | 
            +
                # Remove Enviroment base if it exists. This allows two of the same repos
         | 
| 161 | 
            +
                # in a different location to use the same cache (like capistrano deploys)
         | 
| 162 | 
            +
                def normalize_filename_base(source_filename)
         | 
| 163 | 
            +
                  if @environment.base && source_filename.start_with?(@environment.base)
         | 
| 164 | 
            +
                    '!'+source_filename.delete_prefix(@environment.base).delete_prefix(File::SEPARATOR)
         | 
| 165 | 
            +
                  else
         | 
| 166 | 
            +
                    source_filename
         | 
| 167 | 
            +
                  end
         | 
| 168 | 
            +
                end
         | 
| 169 | 
            +
                
         | 
| 152 170 | 
             
                def process_cache_version
         | 
| 153 171 | 
             
                  return @pcv if @pcv
         | 
| 154 172 |  | 
| 155 173 | 
             
                  f = []
         | 
| 156 174 | 
             
                  all_dependenies(process_dependencies, Set.new, :process_dependencies) do |dep|
         | 
| 157 175 | 
             
                    f << [
         | 
| 158 | 
            -
                       | 
| 176 | 
            +
                      normalize_filename_base(dep.source_file),
         | 
| 159 177 | 
             
                      Digest::SHA256.file(dep.source_file).hexdigest
         | 
| 160 178 | 
             
                    ]
         | 
| 161 179 | 
             
                  end
         | 
| @@ -169,7 +187,7 @@ class Condenser | |
| 169 187 | 
             
                  f = []
         | 
| 170 188 | 
             
                  all_dependenies(export_dependencies, Set.new, :export_dependencies) do |dep|
         | 
| 171 189 | 
             
                    f << [
         | 
| 172 | 
            -
                       | 
| 190 | 
            +
                      normalize_filename_base(dep.source_file),
         | 
| 173 191 | 
             
                      Digest::SHA256.file(dep.source_file).hexdigest
         | 
| 174 192 | 
             
                    ]
         | 
| 175 193 | 
             
                  end
         | 
| @@ -276,6 +294,8 @@ class Condenser | |
| 276 294 |  | 
| 277 295 | 
             
                      data[:digest] = @environment.digestor.digest(data[:source])
         | 
| 278 296 | 
             
                      data[:digest_name] = @environment.digestor.name.sub(/^.*::/, '').downcase
         | 
| 297 | 
            +
                      data[:process_dependencies] = normialize_dependency_names(data[:process_dependencies])
         | 
| 298 | 
            +
                      data[:export_dependencies] = normialize_dependency_names(data[:export_dependencies])
         | 
| 279 299 |  | 
| 280 300 | 
             
                      # Do this here and at the end so cache_key can be calculated if we
         | 
| 281 301 | 
             
                      # run this block
         | 
| @@ -314,6 +334,17 @@ class Condenser | |
| 314 334 | 
             
                  @processed = true
         | 
| 315 335 | 
             
                end
         | 
| 316 336 |  | 
| 337 | 
            +
                def normialize_dependency_names(deps)
         | 
| 338 | 
            +
                  deps.map do |fn|
         | 
| 339 | 
            +
                    if fn.is_a?(String)
         | 
| 340 | 
            +
                      dirname, basename, extensions, mime_types = @environment.decompose_path(fn, source_file)
         | 
| 341 | 
            +
                      [dirname ? File.join(dirname, basename) : basename, mime_types.empty? ? @content_types : mime_types]
         | 
| 342 | 
            +
                    else
         | 
| 343 | 
            +
                      fn
         | 
| 344 | 
            +
                    end
         | 
| 345 | 
            +
                  end
         | 
| 346 | 
            +
                end
         | 
| 347 | 
            +
                
         | 
| 317 348 | 
             
                def export
         | 
| 318 349 | 
             
                  return @export if @export
         | 
| 319 350 |  | 
| @@ -22,6 +22,10 @@ class Condenser | |
| 22 22 | 
             
                  else
         | 
| 23 23 | 
             
                    @semaphore = Mutex.new
         | 
| 24 24 | 
             
                    @listener = Listen.to(*path) do |modified, added, removed|
         | 
| 25 | 
            +
                      modified = Set.new(modified)
         | 
| 26 | 
            +
                      added = Set.new(added)
         | 
| 27 | 
            +
                      removed = Set.new(removed)
         | 
| 28 | 
            +
                      
         | 
| 25 29 | 
             
                      @semaphore.synchronize do
         | 
| 26 30 | 
             
                        @logger.debug { "build cache semaphore locked by #{Thread.current.object_id}" }
         | 
| 27 31 | 
             
                        @logger.debug do
         | 
| @@ -122,16 +126,25 @@ class Condenser | |
| 122 126 |  | 
| 123 127 | 
             
                def []=(value, assets)
         | 
| 124 128 | 
             
                  @lookup_cache[value] = assets
         | 
| 129 | 
            +
                  
         | 
| 130 | 
            +
                  if @fetching.nil?
         | 
| 131 | 
            +
                    begin
         | 
| 132 | 
            +
                      assets.each do |asset|
         | 
| 133 | 
            +
                        @fetching = Set.new
         | 
| 134 | 
            +
                        asset.all_process_dependencies(@fetching).each do |pd|
         | 
| 135 | 
            +
                          @process_dependencies[pd] ||= Set.new
         | 
| 136 | 
            +
                          @process_dependencies[pd] << asset
         | 
| 137 | 
            +
                        end
         | 
| 125 138 |  | 
| 126 | 
            -
             | 
| 127 | 
            -
             | 
| 128 | 
            -
             | 
| 129 | 
            -
                      @process_dependencies[pd] << asset
         | 
| 130 | 
            -
                    end
         | 
| 139 | 
            +
                        @fetching = Set.new
         | 
| 140 | 
            +
                        asset.all_export_dependencies(@fetching).each do |pd|
         | 
| 141 | 
            +
                          @export_dependencies[pd] ||= Set.new
         | 
| 131 142 |  | 
| 132 | 
            -
             | 
| 133 | 
            -
             | 
| 134 | 
            -
                       | 
| 143 | 
            +
                          @export_dependencies[pd] << asset
         | 
| 144 | 
            +
                        end
         | 
| 145 | 
            +
                      end
         | 
| 146 | 
            +
                    ensure
         | 
| 147 | 
            +
                      @fetching = nil
         | 
| 135 148 | 
             
                    end
         | 
| 136 149 | 
             
                  end
         | 
| 137 150 | 
             
                end
         | 
| @@ -55,4 +55,11 @@ module Condenser::ParseHelpers | |
| 55 55 | 
             
                "#{lineno.to_s.rjust(4)}: " + @source[start..uptop] + "\n      #{'-'* (@index-1-start)}#{'^'*(@matched.length)}"
         | 
| 56 56 | 
             
              end
         | 
| 57 57 |  | 
| 58 | 
            +
              def gobble(r)
         | 
| 59 | 
            +
                m = @source.match(r, @index)
         | 
| 60 | 
            +
                if m&.begin(0) == @index
         | 
| 61 | 
            +
                  scan_until(r)
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
             | 
| 58 65 | 
             
            end
         | 
| @@ -95,23 +95,17 @@ class Condenser::BabelProcessor < Condenser::NodeProcessor | |
| 95 95 | 
             
                        ImportDeclaration(path, state) {
         | 
| 96 96 | 
             
                          imports.push(path.node.source.value);
         | 
| 97 97 | 
             
                        },
         | 
| 98 | 
            -
             | 
| 98 | 
            +
             | 
| 99 | 
            +
                        ExportDeclaration(path, state) {
         | 
| 99 100 | 
             
                          hasExports = true;
         | 
| 100 | 
            -
                           | 
| 101 | 
            +
                          if (path.node.source) {
         | 
| 102 | 
            +
                            imports.push(path.node.source.value);
         | 
| 103 | 
            +
                          }
         | 
| 101 104 | 
             
                        },
         | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 105 | 
            +
             | 
| 106 | 
            +
                        ExportDefaultDeclaration(path, state) {
         | 
| 104 107 | 
             
                          defaultExport = true;
         | 
| 105 | 
            -
                        } | 
| 106 | 
            -
                        ExportAllDeclaration(path, state) {
         | 
| 107 | 
            -
                          hasExports = true;
         | 
| 108 | 
            -
                        },
         | 
| 109 | 
            -
                        ExportNamedDeclaration(path, state) {
         | 
| 110 | 
            -
                          hasExports = true;
         | 
| 111 | 
            -
                        },
         | 
| 112 | 
            -
                        ExportSpecifier(path, state) {
         | 
| 113 | 
            -
                          hasExports = true;
         | 
| 114 | 
            -
                        },
         | 
| 108 | 
            +
                        }
         | 
| 115 109 | 
             
                      }
         | 
| 116 110 | 
             
                    };
         | 
| 117 111 | 
             
                  });
         | 
| @@ -15,7 +15,7 @@ class Condenser::JSAnalyzer | |
| 15 15 | 
             
                @source = input[:source]
         | 
| 16 16 | 
             
                @stack =  [:main]
         | 
| 17 17 |  | 
| 18 | 
            -
                input[:export_dependencies] ||=  | 
| 18 | 
            +
                input[:export_dependencies] ||= Set.new
         | 
| 19 19 |  | 
| 20 20 | 
             
                scan_until(/\A(\/\/[^\n]*(\n|\z))*/)
         | 
| 21 21 | 
             
                if matched
         | 
| @@ -28,6 +28,7 @@ class Condenser::JSAnalyzer | |
| 28 28 | 
             
                end
         | 
| 29 29 |  | 
| 30 30 | 
             
                last_postion = nil
         | 
| 31 | 
            +
                last_stack = nil
         | 
| 31 32 | 
             
                while !eos?
         | 
| 32 33 | 
             
                  case @stack.last
         | 
| 33 34 |  | 
| @@ -53,6 +54,32 @@ class Condenser::JSAnalyzer | |
| 53 54 | 
             
                    scan_until(/(;|\n)/)
         | 
| 54 55 | 
             
                    @stack.pop
         | 
| 55 56 |  | 
| 57 | 
            +
                  when :export
         | 
| 58 | 
            +
                    input[:exports] = true;
         | 
| 59 | 
            +
                    input[:default_export] = true if gobble(/\s+default/)
         | 
| 60 | 
            +
                    gobble(/\s+/)
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                    if gobble(/\{/)
         | 
| 63 | 
            +
                      @stack << :brackets
         | 
| 64 | 
            +
                    elsif gobble(/\*/)
         | 
| 65 | 
            +
                      @stack << :export_from
         | 
| 66 | 
            +
                    else
         | 
| 67 | 
            +
                      @stack.pop
         | 
| 68 | 
            +
                    end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  when :export_from
         | 
| 71 | 
            +
                    if gobble(/\s+from\s+/)
         | 
| 72 | 
            +
                      scan_until(/\"|\'/)
         | 
| 73 | 
            +
                      input[:export_dependencies] <<  case matched
         | 
| 74 | 
            +
                      when '"'
         | 
| 75 | 
            +
                        double_quoted_value
         | 
| 76 | 
            +
                      when "'"
         | 
| 77 | 
            +
                        single_quoted_value
         | 
| 78 | 
            +
                      end
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
                    @stack.pop
         | 
| 81 | 
            +
                    @stack.pop
         | 
| 82 | 
            +
                    
         | 
| 56 83 | 
             
                  else
         | 
| 57 84 | 
             
                    scan_until(/(\/\/|\/\*|\/|\(|\)|\{|\}|\"|\'|\`|export|import|\z)/)
         | 
| 58 85 |  | 
| @@ -85,15 +112,17 @@ class Condenser::JSAnalyzer | |
| 85 112 | 
             
                      @stack.push :brackets
         | 
| 86 113 | 
             
                    when '}'
         | 
| 87 114 | 
             
                      case @stack.last
         | 
| 88 | 
            -
                      when : | 
| 115 | 
            +
                      when :tick_statment
         | 
| 116 | 
            +
                        @stack.pop
         | 
| 117 | 
            +
                      when :brackets
         | 
| 89 118 | 
             
                        @stack.pop
         | 
| 119 | 
            +
                        @stack << :export_from if @stack.last == :export
         | 
| 90 120 | 
             
                      else
         | 
| 91 121 | 
             
                        raise unexptected_token("}")
         | 
| 92 122 | 
             
                      end
         | 
| 93 123 | 
             
                    when 'export'
         | 
| 94 124 | 
             
                      if @stack.last == :main
         | 
| 95 | 
            -
                         | 
| 96 | 
            -
                        input[:default_export] = true if next_word == 'default'
         | 
| 125 | 
            +
                        @stack << :export
         | 
| 97 126 | 
             
                      end
         | 
| 98 127 | 
             
                    when 'import'
         | 
| 99 128 | 
             
                      if @stack.last == :main
         | 
| @@ -104,10 +133,13 @@ class Condenser::JSAnalyzer | |
| 104 133 | 
             
                    end
         | 
| 105 134 | 
             
                  end
         | 
| 106 135 |  | 
| 107 | 
            -
                  if last_postion == @index
         | 
| 136 | 
            +
                  if last_postion == @index && last_stack == @stack.last
         | 
| 137 | 
            +
                    syntax_error = Condenser::SyntaxError.new("Error parsing JS file with JSAnalyzer")
         | 
| 138 | 
            +
                    syntax_error.instance_variable_set(:@path, @sourcefile)
         | 
| 108 139 | 
             
                    raise Condenser::SyntaxError, "Error parsing JS file with JSAnalyzer"
         | 
| 109 140 | 
             
                  else
         | 
| 110 141 | 
             
                    last_postion = @index
         | 
| 142 | 
            +
                    last_stack = @stack.last
         | 
| 111 143 | 
             
                  end
         | 
| 112 144 | 
             
                end
         | 
| 113 145 | 
             
              end
         | 
| @@ -121,7 +153,10 @@ class Condenser::JSAnalyzer | |
| 121 153 | 
             
                message << "\n#{lineno.to_s.rjust(4)}: " << @source[start..uptop]
         | 
| 122 154 | 
             
                message << "\n      #{'-'* (@index-1-start)}#{'^'*(@matched.length)}"
         | 
| 123 155 | 
             
                message << "\n"
         | 
| 124 | 
            -
                 | 
| 156 | 
            +
                
         | 
| 157 | 
            +
                syntax_error = Condenser::SyntaxError.new(message)
         | 
| 158 | 
            +
                syntax_error.instance_variable_set(:@path, @sourcefile)
         | 
| 159 | 
            +
                syntax_error
         | 
| 125 160 | 
             
              end
         | 
| 126 161 |  | 
| 127 162 | 
             
              def double_quoted_value
         | 
| @@ -214,7 +214,7 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor | |
| 214 214 | 
             
                        elsif importee.end_with?('*')
         | 
| 215 215 | 
             
                          File.join(File.dirname(importee), '*')
         | 
| 216 216 | 
             
                        else
         | 
| 217 | 
            -
                          @environment.find(importee, importer ?  | 
| 217 | 
            +
                          @environment.find(importee, importer ? (@entry == importer ? @input[:source_file] : importer) : nil, accept: @input[:content_types].last)&.source_file
         | 
| 218 218 | 
             
                        end
         | 
| 219 219 | 
             
                      when 'load'
         | 
| 220 220 | 
             
                        importee = message['args'].first
         | 
    
        data/lib/condenser/resolve.rb
    CHANGED
    
    | @@ -148,11 +148,34 @@ class Condenser | |
| 148 148 | 
             
                  end
         | 
| 149 149 | 
             
                end
         | 
| 150 150 |  | 
| 151 | 
            +
                def has_dir?(path)
         | 
| 152 | 
            +
                  path.count('/') > (path.start_with?('/') ? 1 : 0)
         | 
| 153 | 
            +
                end
         | 
| 154 | 
            +
                
         | 
| 155 | 
            +
                def expand_path(path)
         | 
| 156 | 
            +
                  dir = if path.start_with?('/')
         | 
| 157 | 
            +
                    File.expand_path(path)
         | 
| 158 | 
            +
                  else
         | 
| 159 | 
            +
                    File.expand_path("/#{path}").delete_prefix('/')
         | 
| 160 | 
            +
                  end
         | 
| 161 | 
            +
                  dir.empty? ? nil : dir
         | 
| 162 | 
            +
                end
         | 
| 163 | 
            +
                
         | 
| 151 164 | 
             
                def decompose_path(path, base=nil)
         | 
| 152 | 
            -
                  dirname = path. | 
| 153 | 
            -
             | 
| 154 | 
            -
             | 
| 165 | 
            +
                  dirname = if base && path.start_with?('.')
         | 
| 166 | 
            +
                    if has_dir?(base)
         | 
| 167 | 
            +
                      if has_dir?(path)
         | 
| 168 | 
            +
                        expand_path(File.join(File.dirname(base), File.dirname(path)))
         | 
| 169 | 
            +
                      else
         | 
| 170 | 
            +
                        expand_path(File.dirname(base))
         | 
| 171 | 
            +
                      end
         | 
| 172 | 
            +
                    else
         | 
| 173 | 
            +
                      expand_path(File.dirname(path))
         | 
| 174 | 
            +
                    end
         | 
| 175 | 
            +
                  else
         | 
| 176 | 
            +
                    path.index('/') ? File.dirname(path) : nil
         | 
| 155 177 | 
             
                  end
         | 
| 178 | 
            +
             | 
| 156 179 |  | 
| 157 180 | 
             
                  _, star, basename, extensions = path.match(/(([^\.\/]+)(\.[^\/]+)|\*|[^\/]+)$/).to_a
         | 
| 158 181 | 
             
                  if extensions == '.*'
         | 
    
        data/lib/condenser/version.rb
    CHANGED
    
    
    
        data/test/cache_test.rb
    CHANGED
    
    | @@ -60,6 +60,19 @@ class CacheTest < ActiveSupport::TestCase | |
| 60 60 | 
             
                CSS
         | 
| 61 61 | 
             
              end
         | 
| 62 62 |  | 
| 63 | 
            +
              test 'changing a source file on calls needs_reprocessing! and needs_reexporting! once' do
         | 
| 64 | 
            +
                file 'test.txt.erb', "1<%= 1 + 1 %>3\n"
         | 
| 65 | 
            +
                assert_file 'test.txt', 'text/plain', <<~CSS
         | 
| 66 | 
            +
                123
         | 
| 67 | 
            +
                CSS
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                asset = @env.find('test.txt')
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                asset.expects(:needs_reprocessing!).once
         | 
| 72 | 
            +
                asset.expects(:needs_reexporting!).once
         | 
| 73 | 
            +
                file 'test.txt.erb', "1<%= 1 + 2 %>5\n"
         | 
| 74 | 
            +
              end
         | 
| 75 | 
            +
             | 
| 63 76 | 
             
              test 'changing a js dependency reflects in the next call' do
         | 
| 64 77 | 
             
                file 'main.js', <<-JS
         | 
| 65 78 | 
             
                  import { cube } from 'math';
         | 
| @@ -74,11 +87,11 @@ class CacheTest < ActiveSupport::TestCase | |
| 74 87 | 
             
                JS
         | 
| 75 88 |  | 
| 76 89 | 
             
                assert_exported_file 'main.js', 'application/javascript', <<~CSS
         | 
| 77 | 
            -
                  !function(){ | 
| 90 | 
            +
                  !function(){var o;console.log((o=5)*o)}();
         | 
| 78 91 | 
             
                CSS
         | 
| 79 92 |  | 
| 80 93 | 
             
                assert_exported_file 'main.js', 'application/javascript', <<~CSS
         | 
| 81 | 
            -
                  !function(){ | 
| 94 | 
            +
                  !function(){var o;console.log((o=5)*o)}();
         | 
| 82 95 | 
             
                CSS
         | 
| 83 96 |  | 
| 84 97 | 
             
                file 'math.js', <<-JS
         | 
| @@ -88,7 +101,7 @@ class CacheTest < ActiveSupport::TestCase | |
| 88 101 | 
             
                JS
         | 
| 89 102 |  | 
| 90 103 | 
             
                assert_exported_file 'main.js', 'application/javascript', <<~CSS
         | 
| 91 | 
            -
                  !function(){ | 
| 104 | 
            +
                  !function(){var o;console.log((o=5)*o*o)}();
         | 
| 92 105 | 
             
                CSS
         | 
| 93 106 | 
             
              end
         | 
| 94 107 |  | 
| @@ -123,10 +136,10 @@ class CacheTest < ActiveSupport::TestCase | |
| 123 136 | 
             
                JS
         | 
| 124 137 |  | 
| 125 138 | 
             
                assert_exported_file 'a.js', 'application/javascript', <<~JS
         | 
| 126 | 
            -
                   | 
| 139 | 
            +
                  console.log(5);
         | 
| 127 140 | 
             
                JS
         | 
| 128 141 | 
             
                assert_exported_file 'b.js', 'application/javascript', <<~JS
         | 
| 129 | 
            -
                   | 
| 142 | 
            +
                  console.log(5);
         | 
| 130 143 | 
             
                JS
         | 
| 131 144 |  | 
| 132 145 | 
             
                file 'dep.js', <<-JS
         | 
| @@ -134,12 +147,11 @@ class CacheTest < ActiveSupport::TestCase | |
| 134 147 | 
             
                JS
         | 
| 135 148 |  | 
| 136 149 | 
             
                assert_exported_file 'a.js', 'application/javascript', <<~JS
         | 
| 137 | 
            -
                   | 
| 150 | 
            +
                  console.log(10);
         | 
| 138 151 | 
             
                JS
         | 
| 139 152 | 
             
                assert_exported_file 'b.js', 'application/javascript', <<~JS
         | 
| 140 | 
            -
                   | 
| 153 | 
            +
                  console.log(10);
         | 
| 141 154 | 
             
                JS
         | 
| 142 | 
            -
             | 
| 143 155 | 
             
              end
         | 
| 144 156 |  | 
| 145 157 | 
             
              test 'a dependency is superceeded by a new file' do
         | 
| @@ -158,7 +170,7 @@ class CacheTest < ActiveSupport::TestCase | |
| 158 170 | 
             
                JS
         | 
| 159 171 |  | 
| 160 172 | 
             
                assert_exported_file 'a.js', 'application/javascript', <<~JS
         | 
| 161 | 
            -
                   | 
| 173 | 
            +
                  console.log(5);
         | 
| 162 174 | 
             
                JS
         | 
| 163 175 |  | 
| 164 176 | 
             
                file 'a/dep.js', <<-JS
         | 
| @@ -166,7 +178,7 @@ class CacheTest < ActiveSupport::TestCase | |
| 166 178 | 
             
                JS
         | 
| 167 179 |  | 
| 168 180 | 
             
                assert_exported_file 'a.js', 'application/javascript', <<~JS
         | 
| 169 | 
            -
                   | 
| 181 | 
            +
                  console.log(10);
         | 
| 170 182 | 
             
                JS
         | 
| 171 183 | 
             
              end
         | 
| 172 184 |  | 
| @@ -186,7 +198,7 @@ class CacheTest < ActiveSupport::TestCase | |
| 186 198 | 
             
                JS
         | 
| 187 199 |  | 
| 188 200 | 
             
                assert_exported_file 'a.js', 'application/javascript', <<~JS
         | 
| 189 | 
            -
                   | 
| 201 | 
            +
                  console.log(5);
         | 
| 190 202 | 
             
                JS
         | 
| 191 203 |  | 
| 192 204 | 
             
                file 'a/deps/dep.js', <<-JS
         | 
| @@ -194,7 +206,7 @@ class CacheTest < ActiveSupport::TestCase | |
| 194 206 | 
             
                JS
         | 
| 195 207 |  | 
| 196 208 | 
             
                assert_exported_file 'a.js', 'application/javascript', <<~JS
         | 
| 197 | 
            -
                   | 
| 209 | 
            +
                  console.log(10);
         | 
| 198 210 | 
             
                JS
         | 
| 199 211 |  | 
| 200 212 | 
             
                file 'a/deps/dep.js', <<-JS
         | 
| @@ -202,7 +214,7 @@ class CacheTest < ActiveSupport::TestCase | |
| 202 214 | 
             
                JS
         | 
| 203 215 |  | 
| 204 216 | 
             
                assert_exported_file 'a.js', 'application/javascript', <<~JS
         | 
| 205 | 
            -
                   | 
| 217 | 
            +
                  console.log(20);
         | 
| 206 218 | 
             
                JS
         | 
| 207 219 | 
             
              end
         | 
| 208 220 |  | 
| @@ -259,7 +271,7 @@ class CacheTest < ActiveSupport::TestCase | |
| 259 271 | 
             
                JS
         | 
| 260 272 |  | 
| 261 273 | 
             
                assert_exported_file 'a.js', 'application/javascript', <<~JS
         | 
| 262 | 
            -
             | 
| 274 | 
            +
                console.log("a");
         | 
| 263 275 | 
             
                JS
         | 
| 264 276 |  | 
| 265 277 | 
             
                file 'a.js', <<~JS
         | 
| @@ -269,7 +281,7 @@ class CacheTest < ActiveSupport::TestCase | |
| 269 281 | 
             
                JS
         | 
| 270 282 |  | 
| 271 283 | 
             
                assert_exported_file 'a.js', 'application/javascript', <<~JS
         | 
| 272 | 
            -
                   | 
| 284 | 
            +
                  console.log("a"),console.log("b");
         | 
| 273 285 | 
             
                JS
         | 
| 274 286 |  | 
| 275 287 | 
             
                file 'b.js', <<~JS
         | 
| @@ -277,7 +289,7 @@ class CacheTest < ActiveSupport::TestCase | |
| 277 289 | 
             
                JS
         | 
| 278 290 |  | 
| 279 291 | 
             
                assert_exported_file 'a.js', 'application/javascript', <<~JS
         | 
| 280 | 
            -
                   | 
| 292 | 
            +
                  console.log("a"),console.log("c");
         | 
| 281 293 | 
             
                JS
         | 
| 282 294 | 
             
              end
         | 
| 283 295 |  | 
| @@ -308,5 +320,88 @@ class CacheTest < ActiveSupport::TestCase | |
| 308 320 | 
             
                  body{background:green}body{background:aqua}
         | 
| 309 321 | 
             
                JS
         | 
| 310 322 | 
             
              end
         | 
| 323 | 
            +
              
         | 
| 324 | 
            +
              test 'ensure the build cache only walks the dependency tree once' do
         | 
| 325 | 
            +
                # a
         | 
| 326 | 
            +
                # | |
         | 
| 327 | 
            +
                # b c
         | 
| 328 | 
            +
                #   |
         | 
| 329 | 
            +
                #   d
         | 
| 330 | 
            +
                  
         | 
| 331 | 
            +
                file 'd.js', "export default function d () { console.log('d'); }\n"
         | 
| 332 | 
            +
                file 'b.js', "export default function b () { console.log('b'); }\n"
         | 
| 333 | 
            +
                file 'c.js', <<~JS
         | 
| 334 | 
            +
                  import d from 'd';
         | 
| 335 | 
            +
             | 
| 336 | 
            +
                  export default function c () { console.log('c'); d(); }
         | 
| 337 | 
            +
                JS
         | 
| 338 | 
            +
                file 'a.js', <<~JS
         | 
| 339 | 
            +
                  import b from 'b';
         | 
| 340 | 
            +
                  import c from 'c';
         | 
| 341 | 
            +
                  
         | 
| 342 | 
            +
                  console.log('a'); b(); c();
         | 
| 343 | 
            +
                JS
         | 
| 344 | 
            +
             | 
| 345 | 
            +
                assert_exported_file 'a.js', 'application/javascript', <<~JS
         | 
| 346 | 
            +
                  console.log("a"),console.log("b"),console.log("c"),console.log("d");
         | 
| 347 | 
            +
                JS
         | 
| 348 | 
            +
             | 
| 349 | 
            +
                file 'd.js', "export default function e () { console.log('e'); }\n"
         | 
| 350 | 
            +
             | 
| 351 | 
            +
                pd = @env.build_cache.instance_variable_get(:@process_dependencies)
         | 
| 352 | 
            +
                pd["#{@path}/a.js"] ||= Set.new
         | 
| 353 | 
            +
                pd["#{@path}/b.js"] ||= Set.new
         | 
| 354 | 
            +
                pd["#{@path}/c.js"] ||= Set.new
         | 
| 355 | 
            +
                pd["#{@path}/d.js"] ||= Set.new
         | 
| 356 | 
            +
                pd["#{@path}/a.js"].expects(:<<).with { |a| a.source_file == "#{@path}/a.js" }.once
         | 
| 357 | 
            +
                pd["#{@path}/b.js"].expects(:<<).with { |a| a.source_file == "#{@path}/b.js" }.never
         | 
| 358 | 
            +
                pd["#{@path}/c.js"].expects(:<<).with { |a| a.source_file == "#{@path}/c.js" }.never
         | 
| 359 | 
            +
                pd["#{@path}/d.js"].expects(:<<).with { |a| a.source_file == "#{@path}/d.js" }.once
         | 
| 311 360 |  | 
| 361 | 
            +
                assert_exported_file 'a.js', 'application/javascript', <<~JS
         | 
| 362 | 
            +
                  console.log("a"),console.log("b"),console.log("c"),console.log("e");
         | 
| 363 | 
            +
                JS
         | 
| 364 | 
            +
              end
         | 
| 365 | 
            +
              
         | 
| 366 | 
            +
              test 'same files in diffrent dirs sharing a cache doesnt poison the cache (ie capistrano deploys)' do
         | 
| 367 | 
            +
                cachepath = Dir.mktmpdir
         | 
| 368 | 
            +
                
         | 
| 369 | 
            +
                dir = File.realpath(Dir.mktmpdir)
         | 
| 370 | 
            +
                base1 = File.join(dir, 'a')
         | 
| 371 | 
            +
                base2 = File.join(dir, 'b')
         | 
| 372 | 
            +
                base3 = File.join(dir, 'c')
         | 
| 373 | 
            +
                Dir.mkdir(base1)
         | 
| 374 | 
            +
                Dir.mkdir(base2)
         | 
| 375 | 
            +
             | 
| 376 | 
            +
                [base1, base2, base3].each do |b|
         | 
| 377 | 
            +
                  file 'test.js', "export default function c () { console.log('t'); }\n", base: b
         | 
| 378 | 
            +
                  file 'test/b.js', <<~JS, base: b
         | 
| 379 | 
            +
                    import c from './c';
         | 
| 380 | 
            +
                    export default function b () { console.log('b'); c(); }
         | 
| 381 | 
            +
                  JS
         | 
| 382 | 
            +
                  file 'test/a.js', <<~JS, base: b
         | 
| 383 | 
            +
                    import t from 'test';
         | 
| 384 | 
            +
                    import b from './b';
         | 
| 385 | 
            +
             | 
| 386 | 
            +
                    console.log('a');
         | 
| 387 | 
            +
                    b();
         | 
| 388 | 
            +
                  JS
         | 
| 389 | 
            +
                end
         | 
| 390 | 
            +
             | 
| 391 | 
            +
                file 'test/c.js', "export default function c () { console.log('c'); }\n", base: base1
         | 
| 392 | 
            +
                file 'test/c.js', "export default function c () { console.log('d'); }\n", base: base2
         | 
| 393 | 
            +
                file 'test/c.js', "export default function c () { console.log('e'); }\n", base: base3
         | 
| 394 | 
            +
             | 
| 395 | 
            +
                # Set the cache
         | 
| 396 | 
            +
                env1 = Condenser.new(base1, logger: Logger.new(STDOUT, level: :debug), base: base1, npm_path: @npm_dir, cache: Condenser::Cache::FileStore.new(cachepath))
         | 
| 397 | 
            +
                assert_equal 'console.log("a"),console.log("b"),console.log("c");', env1.find('test/a.js').export.source
         | 
| 398 | 
            +
             | 
| 399 | 
            +
                # Poison the cache
         | 
| 400 | 
            +
                env2 = Condenser.new(base2, logger: Logger.new(STDOUT, level: :debug), base: base2, npm_path: @npm_dir, cache: Condenser::Cache::FileStore.new(cachepath))
         | 
| 401 | 
            +
                assert_equal 'console.log("a"),console.log("b"),console.log("d");', env2.find('test/a.js').export.source
         | 
| 402 | 
            +
             | 
| 403 | 
            +
                # Fails to find dependency change because cache is missing the dependency
         | 
| 404 | 
            +
                env3 = Condenser.new(base3, logger: Logger.new(STDOUT, level: :debug), base: base3, npm_path: @npm_dir, cache: Condenser::Cache::FileStore.new(cachepath))
         | 
| 405 | 
            +
                assert_equal 'console.log("a"),console.log("b"),console.log("e");', env3.find('test/a.js').export.source
         | 
| 406 | 
            +
              end
         | 
| 312 407 | 
             
            end
         | 
    
        data/test/dependency_test.rb
    CHANGED
    
    | @@ -17,7 +17,7 @@ class DependencyTest < ActiveSupport::TestCase | |
| 17 17 | 
             
                JS
         | 
| 18 18 |  | 
| 19 19 | 
             
                asset = @env.find('name.js')
         | 
| 20 | 
            -
                assert_equal asset.instance_variable_get(:@process_dependencies).to_a, ["models | 
| 20 | 
            +
                assert_equal asset.instance_variable_get(:@process_dependencies).to_a, [["models/*", ["application/javascript"]],["helpers/*", ["application/javascript"]]]
         | 
| 21 21 |  | 
| 22 22 |  | 
| 23 23 | 
             
                assert_file 'name.js', 'application/javascript', <<~JS
         | 
| @@ -54,7 +54,7 @@ class DependencyTest < ActiveSupport::TestCase | |
| 54 54 | 
             
                JS
         | 
| 55 55 |  | 
| 56 56 | 
             
                asset = @env.find('name.js')
         | 
| 57 | 
            -
                assert_equal asset.instance_variable_get(:@process_dependencies).to_a, ["models | 
| 57 | 
            +
                assert_equal asset.instance_variable_get(:@process_dependencies).to_a, [["models/*", ["application/javascript"]],["helpers/*", ["application/javascript"]]]
         | 
| 58 58 |  | 
| 59 59 |  | 
| 60 60 | 
             
                assert_file 'name.js', 'application/javascript', <<~JS
         | 
| @@ -74,4 +74,53 @@ class DependencyTest < ActiveSupport::TestCase | |
| 74 74 | 
             
                JS
         | 
| 75 75 | 
             
              end
         | 
| 76 76 |  | 
| 77 | 
            +
              test 'js depending on another file type with JSAnalzyer' do
         | 
| 78 | 
            +
                @env.unregister_preprocessor 'application/javascript', Condenser::BabelProcessor
         | 
| 79 | 
            +
                @env.register_preprocessor 'application/javascript', Condenser::JSAnalyzer
         | 
| 80 | 
            +
                @env.unregister_minifier('application/javascript')
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                file 'a.js', ''
         | 
| 83 | 
            +
                file 'b.rb', ''
         | 
| 84 | 
            +
                file 'models/a.js', ''
         | 
| 85 | 
            +
                file 'models/b.rb', ''
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                file 'name.js.erb', <<~JS
         | 
| 88 | 
            +
                  // depends_on **/*.rb
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                  console.log([<%= Dir.children("#{@path}").sort.map(&:inspect).join(', ') %>]);
         | 
| 91 | 
            +
                JS
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                asset = @env.find('name.js')
         | 
| 94 | 
            +
                assert_equal asset.instance_variable_get(:@process_dependencies).to_a, [["**/*", ["application/ruby"]]]
         | 
| 95 | 
            +
                assert_equal asset.process_dependencies.map(&:source_file), ["#{@path}/b.rb", "#{@path}/models/b.rb"]
         | 
| 96 | 
            +
              end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
              test 'relative imports with JSAnalzyer' do
         | 
| 99 | 
            +
                @env.unregister_preprocessor 'application/javascript', Condenser::BabelProcessor
         | 
| 100 | 
            +
                @env.register_preprocessor 'application/javascript', Condenser::JSAnalyzer
         | 
| 101 | 
            +
                @env.unregister_minifier('application/javascript')
         | 
| 102 | 
            +
                
         | 
| 103 | 
            +
                file 'a/a.js', <<~JS
         | 
| 104 | 
            +
                  export decault function () { console.log("a/a"); }
         | 
| 105 | 
            +
                JS
         | 
| 106 | 
            +
                file 'b/a.js', <<~JS
         | 
| 107 | 
            +
                  export decault function () { console.log("a/a"); }
         | 
| 108 | 
            +
                JS
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                file 'a/b.js', <<~JS
         | 
| 111 | 
            +
                  import fn from './a';
         | 
| 112 | 
            +
                  a();
         | 
| 113 | 
            +
                  console.log("a/b");
         | 
| 114 | 
            +
                JS
         | 
| 115 | 
            +
                file 'b/b.js', <<~JS
         | 
| 116 | 
            +
                  import fn from './a';
         | 
| 117 | 
            +
                  a();
         | 
| 118 | 
            +
                  console.log("b/b");
         | 
| 119 | 
            +
                JS
         | 
| 120 | 
            +
                
         | 
| 121 | 
            +
                asset = @env.find('a/b.js')
         | 
| 122 | 
            +
                assert_equal asset.instance_variable_get(:@export_dependencies).to_a, [["#{@path}/a/a", ["application/javascript"]]]
         | 
| 123 | 
            +
                assert_equal asset.export_dependencies.map(&:source_file), ["#{@path}/a/a.js"]
         | 
| 124 | 
            +
              end
         | 
| 125 | 
            +
              
         | 
| 77 126 | 
             
            end
         | 
| @@ -28,6 +28,28 @@ class CondenserBabelTest < ActiveSupport::TestCase | |
| 28 28 | 
             
                JS
         | 
| 29 29 | 
             
              end
         | 
| 30 30 |  | 
| 31 | 
            +
              test "dependency tracking for a export from" do
         | 
| 32 | 
            +
                file 'c.js', <<~JS
         | 
| 33 | 
            +
                function c() { return 'ok'; }
         | 
| 34 | 
            +
                
         | 
| 35 | 
            +
                export {c}
         | 
| 36 | 
            +
                JS
         | 
| 37 | 
            +
                
         | 
| 38 | 
            +
                file 'b.js', <<~JS
         | 
| 39 | 
            +
                export {c} from 'c';
         | 
| 40 | 
            +
                
         | 
| 41 | 
            +
                JS
         | 
| 42 | 
            +
                
         | 
| 43 | 
            +
                file 'a.js', <<~JS
         | 
| 44 | 
            +
                import {c} from 'b'
         | 
| 45 | 
            +
                
         | 
| 46 | 
            +
                console.log(c());
         | 
| 47 | 
            +
                JS
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                asset = assert_file 'a.js', 'application/javascript'
         | 
| 50 | 
            +
                assert_equal ['/a.js', '/b.js', '/c.js'], asset.all_export_dependencies.map { |path| path.delete_prefix(@path) }
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
             | 
| 31 53 | 
             
              test "error" do
         | 
| 32 54 | 
             
                file 'error.js', <<~JS
         | 
| 33 55 | 
             
                  console.log('this file has an error');
         | 
| @@ -47,6 +69,7 @@ class CondenserBabelTest < ActiveSupport::TestCase | |
| 47 69 | 
             
                      |              ^
         | 
| 48 70 | 
             
                    4 |
         | 
| 49 71 | 
             
                ERROR
         | 
| 72 | 
            +
                assert_equal '/assets/error.js', e.path
         | 
| 50 73 | 
             
              end
         | 
| 51 74 |  | 
| 52 75 | 
             
              test 'not duplicating polyfills' do
         | 
| @@ -83,7 +106,7 @@ class CondenserBabelTest < ActiveSupport::TestCase | |
| 83 106 | 
             
                  	};
         | 
| 84 107 |  | 
| 85 108 | 
             
                  	// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
         | 
| 86 | 
            -
                  	var global$ | 
| 109 | 
            +
                  	var global$8 =
         | 
| 87 110 | 
             
                  	  // eslint-disable-next-line es/no-global-this -- safe
         | 
| 88 111 | 
             
                  	  check(typeof globalThis == 'object' && globalThis) ||
         | 
| 89 112 | 
             
                  	  check(typeof window == 'object' && window) ||
         | 
| @@ -153,25 +176,14 @@ class CondenserBabelTest < ActiveSupport::TestCase | |
| 153 176 | 
             
                  	  if (classofRaw(fn) === 'Function') return uncurryThis$8(fn);
         | 
| 154 177 | 
             
                  	};
         | 
| 155 178 |  | 
| 156 | 
            -
                  	var documentAll$2 = typeof document == 'object' && document.all;
         | 
| 157 | 
            -
             | 
| 158 179 | 
             
                  	// https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot
         | 
| 159 | 
            -
                  	 | 
| 160 | 
            -
                  	var IS_HTMLDDA = typeof documentAll$2 == 'undefined' && documentAll$2 !== undefined;
         | 
| 161 | 
            -
             | 
| 162 | 
            -
                  	var documentAll_1 = {
         | 
| 163 | 
            -
                  	  all: documentAll$2,
         | 
| 164 | 
            -
                  	  IS_HTMLDDA: IS_HTMLDDA
         | 
| 165 | 
            -
                  	};
         | 
| 166 | 
            -
             | 
| 167 | 
            -
                  	var $documentAll$1 = documentAll_1;
         | 
| 168 | 
            -
             | 
| 169 | 
            -
                  	var documentAll$1 = $documentAll$1.all;
         | 
| 180 | 
            +
                  	var documentAll = typeof document == 'object' && document.all;
         | 
| 170 181 |  | 
| 171 182 | 
             
                  	// `IsCallable` abstract operation
         | 
| 172 183 | 
             
                  	// https://tc39.es/ecma262/#sec-iscallable
         | 
| 173 | 
            -
                  	 | 
| 174 | 
            -
             | 
| 184 | 
            +
                  	// eslint-disable-next-line unicorn/no-typeof-undefined -- required for testing
         | 
| 185 | 
            +
                  	var isCallable$7 = typeof documentAll == 'undefined' && documentAll !== undefined ? function (argument) {
         | 
| 186 | 
            +
                  	  return typeof argument == 'function' || argument === documentAll;
         | 
| 175 187 | 
             
                  	} : function (argument) {
         | 
| 176 188 | 
             
                  	  return typeof argument == 'function';
         | 
| 177 189 | 
             
                  	};
         | 
| @@ -261,20 +273,15 @@ class CondenserBabelTest < ActiveSupport::TestCase | |
| 261 273 | 
             
                  	};
         | 
| 262 274 |  | 
| 263 275 | 
             
                  	var isCallable$6 = isCallable$7;
         | 
| 264 | 
            -
                  	var $documentAll = documentAll_1;
         | 
| 265 | 
            -
             | 
| 266 | 
            -
                  	var documentAll = $documentAll.all;
         | 
| 267 276 |  | 
| 268 | 
            -
                  	var isObject$4 =  | 
| 269 | 
            -
                  	  return typeof it == 'object' ? it !== null : isCallable$6(it) || it === documentAll;
         | 
| 270 | 
            -
                  	} : function (it) {
         | 
| 277 | 
            +
                  	var isObject$4 = function (it) {
         | 
| 271 278 | 
             
                  	  return typeof it == 'object' ? it !== null : isCallable$6(it);
         | 
| 272 279 | 
             
                  	};
         | 
| 273 280 |  | 
| 274 281 | 
             
                  	var path$3 = {};
         | 
| 275 282 |  | 
| 276 283 | 
             
                  	var path$2 = path$3;
         | 
| 277 | 
            -
                  	var global$ | 
| 284 | 
            +
                  	var global$7 = global$8;
         | 
| 278 285 | 
             
                  	var isCallable$5 = isCallable$7;
         | 
| 279 286 |  | 
| 280 287 | 
             
                  	var aFunction = function (variable) {
         | 
| @@ -282,8 +289,8 @@ class CondenserBabelTest < ActiveSupport::TestCase | |
| 282 289 | 
             
                  	};
         | 
| 283 290 |  | 
| 284 291 | 
             
                  	var getBuiltIn$1 = function (namespace, method) {
         | 
| 285 | 
            -
                  	  return arguments.length < 2 ? aFunction(path$2[namespace]) || aFunction(global$ | 
| 286 | 
            -
                  	    : path$2[namespace] && path$2[namespace][method] || global$ | 
| 292 | 
            +
                  	  return arguments.length < 2 ? aFunction(path$2[namespace]) || aFunction(global$7[namespace])
         | 
| 293 | 
            +
                  	    : path$2[namespace] && path$2[namespace][method] || global$7[namespace] && global$7[namespace][method];
         | 
| 287 294 | 
             
                  	};
         | 
| 288 295 |  | 
| 289 296 | 
             
                  	var uncurryThis$6 = functionUncurryThis;
         | 
| @@ -292,11 +299,11 @@ class CondenserBabelTest < ActiveSupport::TestCase | |
| 292 299 |  | 
| 293 300 | 
             
                  	var engineUserAgent = typeof navigator != 'undefined' && String(navigator.userAgent) || '';
         | 
| 294 301 |  | 
| 295 | 
            -
                  	var global$ | 
| 302 | 
            +
                  	var global$6 = global$8;
         | 
| 296 303 | 
             
                  	var userAgent = engineUserAgent;
         | 
| 297 304 |  | 
| 298 | 
            -
                  	var process = global$ | 
| 299 | 
            -
                  	var Deno = global$ | 
| 305 | 
            +
                  	var process = global$6.process;
         | 
| 306 | 
            +
                  	var Deno = global$6.Deno;
         | 
| 300 307 | 
             
                  	var versions = process && process.versions || Deno && Deno.version;
         | 
| 301 308 | 
             
                  	var v8 = versions && versions.v8;
         | 
| 302 309 | 
             
                  	var match, version;
         | 
| @@ -323,9 +330,9 @@ class CondenserBabelTest < ActiveSupport::TestCase | |
| 323 330 | 
             
                  	/* eslint-disable es/no-symbol -- required for testing */
         | 
| 324 331 | 
             
                  	var V8_VERSION = engineV8Version;
         | 
| 325 332 | 
             
                  	var fails$4 = fails$8;
         | 
| 326 | 
            -
                  	var global$ | 
| 333 | 
            +
                  	var global$5 = global$8;
         | 
| 327 334 |  | 
| 328 | 
            -
                  	var $String$2 = global$ | 
| 335 | 
            +
                  	var $String$2 = global$5.String;
         | 
| 329 336 |  | 
| 330 337 | 
             
                  	// eslint-disable-next-line es/no-object-getownpropertysymbols -- required for testing
         | 
| 331 338 | 
             
                  	var symbolConstructorDetection = !!Object.getOwnPropertySymbols && !fails$4(function () {
         | 
| @@ -407,42 +414,42 @@ class CondenserBabelTest < ActiveSupport::TestCase | |
| 407 414 | 
             
                  	  throw new $TypeError$3("Can't convert object to primitive value");
         | 
| 408 415 | 
             
                  	};
         | 
| 409 416 |  | 
| 410 | 
            -
                  	var  | 
| 417 | 
            +
                  	var sharedStore = {exports: {}};
         | 
| 411 418 |  | 
| 412 | 
            -
                  	var global$ | 
| 419 | 
            +
                  	var global$4 = global$8;
         | 
| 413 420 |  | 
| 414 421 | 
             
                  	// eslint-disable-next-line es/no-object-defineproperty -- safe
         | 
| 415 422 | 
             
                  	var defineProperty$1 = Object.defineProperty;
         | 
| 416 423 |  | 
| 417 424 | 
             
                  	var defineGlobalProperty$1 = function (key, value) {
         | 
| 418 425 | 
             
                  	  try {
         | 
| 419 | 
            -
                  	    defineProperty$1(global$ | 
| 426 | 
            +
                  	    defineProperty$1(global$4, key, { value: value, configurable: true, writable: true });
         | 
| 420 427 | 
             
                  	  } catch (error) {
         | 
| 421 | 
            -
                  	    global$ | 
| 428 | 
            +
                  	    global$4[key] = value;
         | 
| 422 429 | 
             
                  	  } return value;
         | 
| 423 430 | 
             
                  	};
         | 
| 424 431 |  | 
| 425 | 
            -
                  	var  | 
| 432 | 
            +
                  	var globalThis$1 = global$8;
         | 
| 426 433 | 
             
                  	var defineGlobalProperty = defineGlobalProperty$1;
         | 
| 427 434 |  | 
| 428 435 | 
             
                  	var SHARED = '__core-js_shared__';
         | 
| 429 | 
            -
                  	var store$1 =  | 
| 436 | 
            +
                  	var store$1 = sharedStore.exports = globalThis$1[SHARED] || defineGlobalProperty(SHARED, {});
         | 
| 430 437 |  | 
| 431 | 
            -
                  	 | 
| 432 | 
            -
             | 
| 433 | 
            -
                  	var store = sharedStore;
         | 
| 434 | 
            -
             | 
| 435 | 
            -
                  	(shared$1.exports = function (key, value) {
         | 
| 436 | 
            -
                  	  return store[key] || (store[key] = value !== undefined ? value : {});
         | 
| 437 | 
            -
                  	})('versions', []).push({
         | 
| 438 | 
            -
                  	  version: '3.34.0',
         | 
| 438 | 
            +
                  	(store$1.versions || (store$1.versions = [])).push({
         | 
| 439 | 
            +
                  	  version: '3.37.1',
         | 
| 439 440 | 
             
                  	  mode: 'pure' ,
         | 
| 440 | 
            -
                  	  copyright: '© 2014- | 
| 441 | 
            -
                  	  license: 'https://github.com/zloirock/core-js/blob/v3. | 
| 441 | 
            +
                  	  copyright: '© 2014-2024 Denis Pushkarev (zloirock.ru)',
         | 
| 442 | 
            +
                  	  license: 'https://github.com/zloirock/core-js/blob/v3.37.1/LICENSE',
         | 
| 442 443 | 
             
                  	  source: 'https://github.com/zloirock/core-js'
         | 
| 443 444 | 
             
                  	});
         | 
| 444 445 |  | 
| 445 | 
            -
                  	var  | 
| 446 | 
            +
                  	var sharedStoreExports = sharedStore.exports;
         | 
| 447 | 
            +
             | 
| 448 | 
            +
                  	var store = sharedStoreExports;
         | 
| 449 | 
            +
             | 
| 450 | 
            +
                  	var shared$1 = function (key, value) {
         | 
| 451 | 
            +
                  	  return store[key] || (store[key] = value || {});
         | 
| 452 | 
            +
                  	};
         | 
| 446 453 |  | 
| 447 454 | 
             
                  	var requireObjectCoercible = requireObjectCoercible$2;
         | 
| 448 455 |  | 
| @@ -476,8 +483,8 @@ class CondenserBabelTest < ActiveSupport::TestCase | |
| 476 483 | 
             
                  	  return 'Symbol(' + (key === undefined ? '' : key) + ')_' + toString(++id + postfix, 36);
         | 
| 477 484 | 
             
                  	};
         | 
| 478 485 |  | 
| 479 | 
            -
                  	var global$3 = global$ | 
| 480 | 
            -
                  	var shared =  | 
| 486 | 
            +
                  	var global$3 = global$8;
         | 
| 487 | 
            +
                  	var shared = shared$1;
         | 
| 481 488 | 
             
                  	var hasOwn$3 = hasOwnProperty_1;
         | 
| 482 489 | 
             
                  	var uid = uid$1;
         | 
| 483 490 | 
             
                  	var NATIVE_SYMBOL = symbolConstructorDetection;
         | 
| @@ -531,7 +538,7 @@ class CondenserBabelTest < ActiveSupport::TestCase | |
| 531 538 | 
             
                  	  return isSymbol(key) ? key : key + '';
         | 
| 532 539 | 
             
                  	};
         | 
| 533 540 |  | 
| 534 | 
            -
                  	var global$2 = global$ | 
| 541 | 
            +
                  	var global$2 = global$8;
         | 
| 535 542 | 
             
                  	var isObject$1 = isObject$4;
         | 
| 536 543 |  | 
| 537 544 | 
             
                  	var document$1 = global$2.document;
         | 
| @@ -695,7 +702,7 @@ class CondenserBabelTest < ActiveSupport::TestCase | |
| 695 702 | 
             
                  	  return object;
         | 
| 696 703 | 
             
                  	};
         | 
| 697 704 |  | 
| 698 | 
            -
                  	var global$1 = global$ | 
| 705 | 
            +
                  	var global$1 = global$8;
         | 
| 699 706 | 
             
                  	var apply = functionApply;
         | 
| 700 707 | 
             
                  	var uncurryThis$2 = functionUncurryThisClause;
         | 
| 701 708 | 
             
                  	var isCallable = isCallable$7;
         | 
| @@ -705,6 +712,8 @@ class CondenserBabelTest < ActiveSupport::TestCase | |
| 705 712 | 
             
                  	var bind = functionBindContext;
         | 
| 706 713 | 
             
                  	var createNonEnumerableProperty = createNonEnumerableProperty$1;
         | 
| 707 714 | 
             
                  	var hasOwn$1 = hasOwnProperty_1;
         | 
| 715 | 
            +
                  	// add debugging info
         | 
| 716 | 
            +
             | 
| 708 717 |  | 
| 709 718 | 
             
                  	var wrapConstructor = function (NativeConstructor) {
         | 
| 710 719 | 
             
                  	  var Wrapper = function (a, b, c) {
         | 
| @@ -741,7 +750,7 @@ class CondenserBabelTest < ActiveSupport::TestCase | |
| 741 750 | 
             
                  	  var STATIC = options.stat;
         | 
| 742 751 | 
             
                  	  var PROTO = options.proto;
         | 
| 743 752 |  | 
| 744 | 
            -
                  	  var nativeSource = GLOBAL ? global$1 : STATIC ? global$1[TARGET] :  | 
| 753 | 
            +
                  	  var nativeSource = GLOBAL ? global$1 : STATIC ? global$1[TARGET] : global$1[TARGET] && global$1[TARGET].prototype;
         | 
| 745 754 |  | 
| 746 755 | 
             
                  	  var target = GLOBAL ? path$1 : path$1[TARGET] || createNonEnumerableProperty(path$1, TARGET, {})[TARGET];
         | 
| 747 756 | 
             
                  	  var targetPrototype = target.prototype;
         | 
| @@ -764,7 +773,7 @@ class CondenserBabelTest < ActiveSupport::TestCase | |
| 764 773 | 
             
                  	    // export native or implementation
         | 
| 765 774 | 
             
                  	    sourceProperty = (USE_NATIVE && nativeProperty) ? nativeProperty : source[key];
         | 
| 766 775 |  | 
| 767 | 
            -
                  	    if ( | 
| 776 | 
            +
                  	    if (!FORCED && !PROTO && typeof targetProperty == typeof sourceProperty) continue;
         | 
| 768 777 |  | 
| 769 778 | 
             
                  	    // bind methods to global for calling from export context
         | 
| 770 779 | 
             
                  	    if (options.bind && USE_NATIVE) resultProperty = bind(sourceProperty, global$1);
         | 
| @@ -838,7 +847,8 @@ class CondenserBabelTest < ActiveSupport::TestCase | |
| 838 847 | 
             
                  	// `ToLength` abstract operation
         | 
| 839 848 | 
             
                  	// https://tc39.es/ecma262/#sec-tolength
         | 
| 840 849 | 
             
                  	var toLength$1 = function (argument) {
         | 
| 841 | 
            -
                  	   | 
| 850 | 
            +
                  	  var len = toIntegerOrInfinity(argument);
         | 
| 851 | 
            +
                  	  return len > 0 ? min(len, 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
         | 
| 842 852 | 
             
                  	};
         | 
| 843 853 |  | 
| 844 854 | 
             
                  	var toLength = toLength$1;
         | 
| @@ -858,6 +868,7 @@ class CondenserBabelTest < ActiveSupport::TestCase | |
| 858 868 | 
             
                  	  return function ($this, el, fromIndex) {
         | 
| 859 869 | 
             
                  	    var O = toIndexedObject$1($this);
         | 
| 860 870 | 
             
                  	    var length = lengthOfArrayLike(O);
         | 
| 871 | 
            +
                  	    if (length === 0) return !IS_INCLUDES && -1;
         | 
| 861 872 | 
             
                  	    var index = toAbsoluteIndex(fromIndex, length);
         | 
| 862 873 | 
             
                  	    var value;
         | 
| 863 874 | 
             
                  	    // Array#includes uses SameValueZero equality algorithm
         | 
| @@ -248,4 +248,39 @@ class JSAnalyzerTest < ActiveSupport::TestCase | |
| 248 248 | 
             
                assert_equal ['a.js', 'b.js'], asset.export_dependencies.map(&:filename)
         | 
| 249 249 | 
             
              end
         | 
| 250 250 |  | 
| 251 | 
            +
              test "dependency tracking for a export from" do
         | 
| 252 | 
            +
                file 'c.js', <<~JS
         | 
| 253 | 
            +
                function c() { return 'ok'; }
         | 
| 254 | 
            +
                
         | 
| 255 | 
            +
                export {c}
         | 
| 256 | 
            +
                JS
         | 
| 257 | 
            +
                
         | 
| 258 | 
            +
                file 'b.js', <<~JS
         | 
| 259 | 
            +
                export {c} from 'c';
         | 
| 260 | 
            +
                
         | 
| 261 | 
            +
                JS
         | 
| 262 | 
            +
                
         | 
| 263 | 
            +
                file 'a.js', <<~JS
         | 
| 264 | 
            +
                import {c} from 'b'
         | 
| 265 | 
            +
                
         | 
| 266 | 
            +
                console.log(c());
         | 
| 267 | 
            +
                JS
         | 
| 268 | 
            +
             | 
| 269 | 
            +
                asset = assert_file 'a.js', 'application/javascript'
         | 
| 270 | 
            +
                assert_equal ['/a.js', '/b.js', '/c.js'], asset.all_export_dependencies.map { |path| path.delete_prefix(@path) }
         | 
| 271 | 
            +
              end
         | 
| 272 | 
            +
              
         | 
| 273 | 
            +
              test 'exporting a nested object' do
         | 
| 274 | 
            +
                file 't.js', <<~JS
         | 
| 275 | 
            +
                  export default {
         | 
| 276 | 
            +
                      registry: {
         | 
| 277 | 
            +
                          boolean: true,
         | 
| 278 | 
            +
                          integer: 1
         | 
| 279 | 
            +
                      }
         | 
| 280 | 
            +
                  };
         | 
| 281 | 
            +
                JS
         | 
| 282 | 
            +
                
         | 
| 283 | 
            +
                asset = assert_file 't.js', 'application/javascript'
         | 
| 284 | 
            +
              end
         | 
| 285 | 
            +
             | 
| 251 286 | 
             
            end
         | 
    
        data/test/resolve_test.rb
    CHANGED
    
    | @@ -35,6 +35,16 @@ class ResolveTest < ActiveSupport::TestCase | |
| 35 35 | 
             
                assert_equal ['test', '*', ['.js'], ['application/javascript']], @env.decompose_path('test/*.js')
         | 
| 36 36 | 
             
                assert_equal ['test/*', '*', ['.js'], ['application/javascript']], @env.decompose_path('test/*/*.js')
         | 
| 37 37 | 
             
                assert_equal ['test/**', '*', ['.js'], ['application/javascript']], @env.decompose_path('test/**/*.js')
         | 
| 38 | 
            +
                
         | 
| 39 | 
            +
                assert_equal ['a', 'test', ['.js'], ['application/javascript']], @env.decompose_path('./test.js', 'a/b.js')
         | 
| 40 | 
            +
                assert_equal [nil, 'test', ['.js'], ['application/javascript']], @env.decompose_path('./test.js', 'b.js')
         | 
| 41 | 
            +
                assert_equal ['a/folder', 'test', ['.js'], ['application/javascript']], @env.decompose_path('./folder/test.js', 'a/b.js')
         | 
| 42 | 
            +
                assert_equal ['folder', 'test', ['.js'], ['application/javascript']], @env.decompose_path('./folder/test.js', 'b.js')
         | 
| 43 | 
            +
                
         | 
| 44 | 
            +
                assert_equal [nil, 'test', ['.js'], ['application/javascript']], @env.decompose_path('../test.js', 'a/b.js')
         | 
| 45 | 
            +
                assert_equal ["/", 'test', ['.js'], ['application/javascript']], @env.decompose_path('../test.js', '/a/b.js')
         | 
| 46 | 
            +
                assert_equal ["folder", 'test', ['.js'], ['application/javascript']], @env.decompose_path('../folder/test.js', 'a/b.js')
         | 
| 47 | 
            +
                assert_equal ["/folder", 'test', ['.js'], ['application/javascript']], @env.decompose_path('../folder/test.js', '/a/b.js')
         | 
| 38 48 | 
             
              end
         | 
| 39 49 |  | 
| 40 50 | 
             
              test 'resolve' do
         | 
    
        data/test/server_test.rb
    CHANGED
    
    | @@ -27,10 +27,10 @@ class ServerTest < ActiveSupport::TestCase | |
| 27 27 | 
             
              test "serve single source file" do
         | 
| 28 28 | 
             
                get "/assets/foo.js"
         | 
| 29 29 | 
             
                assert_equal 200, last_response.status
         | 
| 30 | 
            -
                assert_equal " | 
| 30 | 
            +
                assert_equal "15", last_response.headers['Content-Length']
         | 
| 31 31 | 
             
                assert_equal "Accept-Encoding", last_response.headers['Vary']
         | 
| 32 32 | 
             
                assert_equal <<~JS.strip, last_response.body
         | 
| 33 | 
            -
                   | 
| 33 | 
            +
                  console.log(1);
         | 
| 34 34 | 
             
                JS
         | 
| 35 35 | 
             
              end
         | 
| 36 36 |  | 
| @@ -54,7 +54,7 @@ class ServerTest < ActiveSupport::TestCase | |
| 54 54 |  | 
| 55 55 | 
             
                get "/assets/main.js"
         | 
| 56 56 | 
             
                assert_equal <<~JS.strip, last_response.body
         | 
| 57 | 
            -
                  !function(){ | 
| 57 | 
            +
                  !function(){var o;console.log((o=5)*o*o)}();
         | 
| 58 58 | 
             
                JS
         | 
| 59 59 | 
             
              end
         | 
| 60 60 |  | 
| @@ -73,7 +73,7 @@ class ServerTest < ActiveSupport::TestCase | |
| 73 73 | 
             
              test "serve source with etag headers" do
         | 
| 74 74 | 
             
                get "/assets/foo.js"
         | 
| 75 75 |  | 
| 76 | 
            -
                digest = ' | 
| 76 | 
            +
                digest = '35c146f76e129477c64061bc84511e1090f3d4d8059713e6663dd4b35b1f7642'
         | 
| 77 77 | 
             
                assert_equal "\"#{digest}\"", last_response.headers['ETag']
         | 
| 78 78 | 
             
              end
         | 
| 79 79 |  | 
| @@ -107,8 +107,8 @@ class ServerTest < ActiveSupport::TestCase | |
| 107 107 | 
             
                  'HTTP_IF_NONE_MATCH' => "nope"
         | 
| 108 108 |  | 
| 109 109 | 
             
                assert_equal 200, last_response.status
         | 
| 110 | 
            -
                assert_equal '" | 
| 111 | 
            -
                assert_equal ' | 
| 110 | 
            +
                assert_equal '"35c146f76e129477c64061bc84511e1090f3d4d8059713e6663dd4b35b1f7642"', last_response.headers['ETag']
         | 
| 111 | 
            +
                assert_equal '15', last_response.headers['Content-Length']
         | 
| 112 112 | 
             
              end
         | 
| 113 113 |  | 
| 114 114 | 
             
              test "not modified partial response with fingerprint and if-none-match etags match" do
         | 
| @@ -167,8 +167,8 @@ class ServerTest < ActiveSupport::TestCase | |
| 167 167 | 
             
                  'HTTP_IF_MATCH' => etag
         | 
| 168 168 |  | 
| 169 169 | 
             
                assert_equal 200, last_response.status
         | 
| 170 | 
            -
                assert_equal '" | 
| 171 | 
            -
                assert_equal ' | 
| 170 | 
            +
                assert_equal '"35c146f76e129477c64061bc84511e1090f3d4d8059713e6663dd4b35b1f7642"', last_response.headers['ETag']
         | 
| 171 | 
            +
                assert_equal '15', last_response.headers['Content-Length']
         | 
| 172 172 | 
             
              end
         | 
| 173 173 |  | 
| 174 174 | 
             
              test "precondition failed with if-match is a mismatch" do
         | 
| @@ -253,7 +253,7 @@ class ServerTest < ActiveSupport::TestCase | |
| 253 253 | 
             
                JS
         | 
| 254 254 | 
             
                get "/assets/%E6%97%A5%E6%9C%AC%E8%AA%9E.js"
         | 
| 255 255 | 
             
                assert_equal <<~JS.strip, last_response.body
         | 
| 256 | 
            -
                   | 
| 256 | 
            +
                  console.log("日本語");
         | 
| 257 257 | 
             
                JS
         | 
| 258 258 | 
             
              end
         | 
| 259 259 |  | 
    
        data/test/test_helper.rb
    CHANGED
    
    | @@ -53,9 +53,10 @@ class ActiveSupport::TestCase | |
| 53 53 | 
             
                assert_equal json, jbuild(&block)
         | 
| 54 54 | 
             
              end
         | 
| 55 55 |  | 
| 56 | 
            -
              def file(name, source)
         | 
| 57 | 
            -
                 | 
| 58 | 
            -
                 | 
| 56 | 
            +
              def file(name, source, base: nil)
         | 
| 57 | 
            +
                base ||= @path
         | 
| 58 | 
            +
                dir = name.include?('/') ? File.join(base, File.dirname(name)) : base
         | 
| 59 | 
            +
                path = File.join(base, name)
         | 
| 59 60 |  | 
| 60 61 | 
             
                FileUtils.mkdir_p(dir)
         | 
| 61 62 | 
             
                if File.exist?(path)
         | 
| @@ -78,6 +79,7 @@ class ActiveSupport::TestCase | |
| 78 79 | 
             
                assert_equal path.delete_prefix('/'),     asset.filename
         | 
| 79 80 | 
             
                assert_equal Array(mime_types),           asset.content_types
         | 
| 80 81 | 
             
                assert_equal(source.rstrip, asset.source.rstrip) if !source.nil?
         | 
| 82 | 
            +
                asset
         | 
| 81 83 | 
             
              end
         | 
| 82 84 |  | 
| 83 85 | 
             
              def assert_exported_file(path, mime_types, source=nil)
         | 
| @@ -88,6 +90,7 @@ class ActiveSupport::TestCase | |
| 88 90 | 
             
                assert_equal path,                        asset.filename
         | 
| 89 91 | 
             
                assert_equal Array(mime_types),           asset.content_types
         | 
| 90 92 | 
             
                assert_equal(source.rstrip, asset.source.rstrip) if !source.nil?
         | 
| 93 | 
            +
                asset
         | 
| 91 94 | 
             
              end
         | 
| 92 95 |  | 
| 93 96 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: condenser
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: '1. | 
| 4 | 
            +
              version: '1.4'
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Jon Bracy
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2024-06-12 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: erubi
         | 
| @@ -398,7 +398,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 398 398 | 
             
                - !ruby/object:Gem::Version
         | 
| 399 399 | 
             
                  version: '0'
         | 
| 400 400 | 
             
            requirements: []
         | 
| 401 | 
            -
            rubygems_version: 3.4 | 
| 401 | 
            +
            rubygems_version: 3.5.4
         | 
| 402 402 | 
             
            signing_key:
         | 
| 403 403 | 
             
            specification_version: 4
         | 
| 404 404 | 
             
            summary: A Rack-based asset packaging system
         |