sprockets 2.2.3 → 4.0.0
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 +5 -5
 - data/CHANGELOG.md +68 -0
 - data/README.md +482 -255
 - data/bin/sprockets +20 -7
 - data/lib/rake/sprocketstask.rb +28 -15
 - data/lib/sprockets/add_source_map_comment_to_asset_processor.rb +60 -0
 - data/lib/sprockets/asset.rb +142 -207
 - data/lib/sprockets/autoload/babel.rb +8 -0
 - data/lib/sprockets/autoload/closure.rb +8 -0
 - data/lib/sprockets/autoload/coffee_script.rb +8 -0
 - data/lib/sprockets/autoload/eco.rb +8 -0
 - data/lib/sprockets/autoload/ejs.rb +8 -0
 - data/lib/sprockets/autoload/jsminc.rb +8 -0
 - data/lib/sprockets/autoload/sass.rb +8 -0
 - data/lib/sprockets/autoload/sassc.rb +8 -0
 - data/lib/sprockets/autoload/uglifier.rb +8 -0
 - data/lib/sprockets/autoload/yui.rb +8 -0
 - data/lib/sprockets/autoload/zopfli.rb +7 -0
 - data/lib/sprockets/autoload.rb +16 -0
 - data/lib/sprockets/babel_processor.rb +66 -0
 - data/lib/sprockets/base.rb +89 -249
 - data/lib/sprockets/bower.rb +61 -0
 - data/lib/sprockets/bundle.rb +105 -0
 - data/lib/sprockets/cache/file_store.rb +190 -14
 - data/lib/sprockets/cache/memory_store.rb +75 -0
 - data/lib/sprockets/cache/null_store.rb +54 -0
 - data/lib/sprockets/cache.rb +271 -0
 - data/lib/sprockets/cached_environment.rb +64 -0
 - data/lib/sprockets/closure_compressor.rb +48 -0
 - data/lib/sprockets/coffee_script_processor.rb +39 -0
 - data/lib/sprockets/compressing.rb +134 -0
 - data/lib/sprockets/configuration.rb +79 -0
 - data/lib/sprockets/context.rb +204 -135
 - data/lib/sprockets/dependencies.rb +74 -0
 - data/lib/sprockets/digest_utils.rb +200 -0
 - data/lib/sprockets/directive_processor.rb +224 -216
 - data/lib/sprockets/eco_processor.rb +33 -0
 - data/lib/sprockets/ejs_processor.rb +32 -0
 - data/lib/sprockets/encoding_utils.rb +262 -0
 - data/lib/sprockets/environment.rb +23 -68
 - data/lib/sprockets/erb_processor.rb +37 -0
 - data/lib/sprockets/errors.rb +6 -13
 - data/lib/sprockets/exporters/base.rb +72 -0
 - data/lib/sprockets/exporters/file_exporter.rb +24 -0
 - data/lib/sprockets/exporters/zlib_exporter.rb +33 -0
 - data/lib/sprockets/exporters/zopfli_exporter.rb +14 -0
 - data/lib/sprockets/exporting.rb +73 -0
 - data/lib/sprockets/file_reader.rb +16 -0
 - data/lib/sprockets/http_utils.rb +135 -0
 - data/lib/sprockets/jsminc_compressor.rb +32 -0
 - data/lib/sprockets/jst_processor.rb +36 -19
 - data/lib/sprockets/loader.rb +343 -0
 - data/lib/sprockets/manifest.rb +231 -96
 - data/lib/sprockets/manifest_utils.rb +48 -0
 - data/lib/sprockets/mime.rb +80 -32
 - data/lib/sprockets/npm.rb +52 -0
 - data/lib/sprockets/path_dependency_utils.rb +77 -0
 - data/lib/sprockets/path_digest_utils.rb +48 -0
 - data/lib/sprockets/path_utils.rb +367 -0
 - data/lib/sprockets/paths.rb +82 -0
 - data/lib/sprockets/preprocessors/default_source_map.rb +49 -0
 - data/lib/sprockets/processing.rb +140 -192
 - data/lib/sprockets/processor_utils.rb +169 -0
 - data/lib/sprockets/resolve.rb +295 -0
 - data/lib/sprockets/sass_cache_store.rb +30 -0
 - data/lib/sprockets/sass_compressor.rb +63 -0
 - data/lib/sprockets/sass_functions.rb +3 -0
 - data/lib/sprockets/sass_importer.rb +3 -0
 - data/lib/sprockets/sass_processor.rb +313 -0
 - data/lib/sprockets/sassc_compressor.rb +56 -0
 - data/lib/sprockets/sassc_processor.rb +297 -0
 - data/lib/sprockets/server.rb +138 -90
 - data/lib/sprockets/source_map_processor.rb +66 -0
 - data/lib/sprockets/source_map_utils.rb +483 -0
 - data/lib/sprockets/transformers.rb +173 -0
 - data/lib/sprockets/uglifier_compressor.rb +66 -0
 - data/lib/sprockets/unloaded_asset.rb +139 -0
 - data/lib/sprockets/uri_tar.rb +99 -0
 - data/lib/sprockets/uri_utils.rb +191 -0
 - data/lib/sprockets/utils/gzip.rb +99 -0
 - data/lib/sprockets/utils.rb +186 -53
 - data/lib/sprockets/version.rb +2 -1
 - data/lib/sprockets/yui_compressor.rb +56 -0
 - data/lib/sprockets.rb +217 -52
 - metadata +250 -59
 - data/LICENSE +0 -21
 - data/lib/sprockets/asset_attributes.rb +0 -126
 - data/lib/sprockets/bundled_asset.rb +0 -79
 - data/lib/sprockets/caching.rb +0 -96
 - data/lib/sprockets/charset_normalizer.rb +0 -41
 - data/lib/sprockets/eco_template.rb +0 -38
 - data/lib/sprockets/ejs_template.rb +0 -37
 - data/lib/sprockets/engines.rb +0 -74
 - data/lib/sprockets/index.rb +0 -99
 - data/lib/sprockets/processed_asset.rb +0 -152
 - data/lib/sprockets/processor.rb +0 -32
 - data/lib/sprockets/safety_colons.rb +0 -28
 - data/lib/sprockets/static_asset.rb +0 -57
 - data/lib/sprockets/trail.rb +0 -90
 
| 
         @@ -0,0 +1,200 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'digest/md5'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'digest/sha1'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'digest/sha2'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'set'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            module Sprockets
         
     | 
| 
      
 8 
     | 
    
         
            +
              # Internal: Hash functions and digest related utilities. Mixed into
         
     | 
| 
      
 9 
     | 
    
         
            +
              # Environment.
         
     | 
| 
      
 10 
     | 
    
         
            +
              module DigestUtils
         
     | 
| 
      
 11 
     | 
    
         
            +
                extend self
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                # Internal: Default digest class.
         
     | 
| 
      
 14 
     | 
    
         
            +
                #
         
     | 
| 
      
 15 
     | 
    
         
            +
                # Returns a Digest::Base subclass.
         
     | 
| 
      
 16 
     | 
    
         
            +
                def digest_class
         
     | 
| 
      
 17 
     | 
    
         
            +
                  Digest::SHA256
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                # Internal: Maps digest bytesize to the digest class.
         
     | 
| 
      
 21 
     | 
    
         
            +
                DIGEST_SIZES = {
         
     | 
| 
      
 22 
     | 
    
         
            +
                  16 => Digest::MD5,
         
     | 
| 
      
 23 
     | 
    
         
            +
                  20 => Digest::SHA1,
         
     | 
| 
      
 24 
     | 
    
         
            +
                  32 => Digest::SHA256,
         
     | 
| 
      
 25 
     | 
    
         
            +
                  48 => Digest::SHA384,
         
     | 
| 
      
 26 
     | 
    
         
            +
                  64 => Digest::SHA512
         
     | 
| 
      
 27 
     | 
    
         
            +
                }
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                # Internal: Detect digest class hash algorithm for digest bytes.
         
     | 
| 
      
 30 
     | 
    
         
            +
                #
         
     | 
| 
      
 31 
     | 
    
         
            +
                # While not elegant, all the supported digests have a unique bytesize.
         
     | 
| 
      
 32 
     | 
    
         
            +
                #
         
     | 
| 
      
 33 
     | 
    
         
            +
                # Returns Digest::Base or nil.
         
     | 
| 
      
 34 
     | 
    
         
            +
                def detect_digest_class(bytes)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  DIGEST_SIZES[bytes.bytesize]
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                ADD_VALUE_TO_DIGEST = {
         
     | 
| 
      
 39 
     | 
    
         
            +
                  String     => ->(val, digest) { digest << val },
         
     | 
| 
      
 40 
     | 
    
         
            +
                  FalseClass => ->(val, digest) { digest << 'FalseClass'.freeze },
         
     | 
| 
      
 41 
     | 
    
         
            +
                  TrueClass  => ->(val, digest) { digest << 'TrueClass'.freeze  },
         
     | 
| 
      
 42 
     | 
    
         
            +
                  NilClass   => ->(val, digest) { digest << 'NilClass'.freeze   },
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  Symbol => ->(val, digest) {
         
     | 
| 
      
 45 
     | 
    
         
            +
                    digest << 'Symbol'.freeze
         
     | 
| 
      
 46 
     | 
    
         
            +
                    digest << val.to_s
         
     | 
| 
      
 47 
     | 
    
         
            +
                  },
         
     | 
| 
      
 48 
     | 
    
         
            +
                  Integer => ->(val, digest) {
         
     | 
| 
      
 49 
     | 
    
         
            +
                    digest << 'Integer'.freeze
         
     | 
| 
      
 50 
     | 
    
         
            +
                    digest << val.to_s
         
     | 
| 
      
 51 
     | 
    
         
            +
                  },
         
     | 
| 
      
 52 
     | 
    
         
            +
                  Array => ->(val, digest) {
         
     | 
| 
      
 53 
     | 
    
         
            +
                    digest << 'Array'.freeze
         
     | 
| 
      
 54 
     | 
    
         
            +
                    val.each do |element|
         
     | 
| 
      
 55 
     | 
    
         
            +
                      ADD_VALUE_TO_DIGEST[element.class].call(element, digest)
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
                  },
         
     | 
| 
      
 58 
     | 
    
         
            +
                  Hash => ->(val, digest) {
         
     | 
| 
      
 59 
     | 
    
         
            +
                    digest << 'Hash'.freeze
         
     | 
| 
      
 60 
     | 
    
         
            +
                    val.sort.each do |array|
         
     | 
| 
      
 61 
     | 
    
         
            +
                      ADD_VALUE_TO_DIGEST[Array].call(array, digest)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end
         
     | 
| 
      
 63 
     | 
    
         
            +
                  },
         
     | 
| 
      
 64 
     | 
    
         
            +
                  Set => ->(val, digest) {
         
     | 
| 
      
 65 
     | 
    
         
            +
                    digest << 'Set'.freeze
         
     | 
| 
      
 66 
     | 
    
         
            +
                    ADD_VALUE_TO_DIGEST[Array].call(val, digest)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  },
         
     | 
| 
      
 68 
     | 
    
         
            +
                  Encoding => ->(val, digest) {
         
     | 
| 
      
 69 
     | 
    
         
            +
                    digest << 'Encoding'.freeze
         
     | 
| 
      
 70 
     | 
    
         
            +
                    digest << val.name
         
     | 
| 
      
 71 
     | 
    
         
            +
                  },
         
     | 
| 
      
 72 
     | 
    
         
            +
                }
         
     | 
| 
      
 73 
     | 
    
         
            +
                if 0.class != Integer # Ruby < 2.4
         
     | 
| 
      
 74 
     | 
    
         
            +
                  ADD_VALUE_TO_DIGEST[Fixnum] = ->(val, digest) {
         
     | 
| 
      
 75 
     | 
    
         
            +
                    digest << 'Integer'.freeze
         
     | 
| 
      
 76 
     | 
    
         
            +
                    digest << val.to_s
         
     | 
| 
      
 77 
     | 
    
         
            +
                  }
         
     | 
| 
      
 78 
     | 
    
         
            +
                  ADD_VALUE_TO_DIGEST[Bignum] = ->(val, digest) {
         
     | 
| 
      
 79 
     | 
    
         
            +
                    digest << 'Integer'.freeze
         
     | 
| 
      
 80 
     | 
    
         
            +
                    digest << val.to_s
         
     | 
| 
      
 81 
     | 
    
         
            +
                  }
         
     | 
| 
      
 82 
     | 
    
         
            +
                end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                ADD_VALUE_TO_DIGEST.compare_by_identity.rehash
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                ADD_VALUE_TO_DIGEST.default_proc = ->(_, val) {
         
     | 
| 
      
 87 
     | 
    
         
            +
                  raise TypeError, "couldn't digest #{ val }"
         
     | 
| 
      
 88 
     | 
    
         
            +
                }
         
     | 
| 
      
 89 
     | 
    
         
            +
                private_constant :ADD_VALUE_TO_DIGEST
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                # Internal: Generate a hexdigest for a nested JSON serializable object.
         
     | 
| 
      
 92 
     | 
    
         
            +
                #
         
     | 
| 
      
 93 
     | 
    
         
            +
                # This is used for generating cache keys, so its pretty important its
         
     | 
| 
      
 94 
     | 
    
         
            +
                # wicked fast. Microbenchmarks away!
         
     | 
| 
      
 95 
     | 
    
         
            +
                #
         
     | 
| 
      
 96 
     | 
    
         
            +
                # obj - A JSON serializable object.
         
     | 
| 
      
 97 
     | 
    
         
            +
                #
         
     | 
| 
      
 98 
     | 
    
         
            +
                # Returns a String digest of the object.
         
     | 
| 
      
 99 
     | 
    
         
            +
                def digest(obj)
         
     | 
| 
      
 100 
     | 
    
         
            +
                  build_digest(obj).digest
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                # Internal: Generate a hexdigest for a nested JSON serializable object.
         
     | 
| 
      
 104 
     | 
    
         
            +
                #
         
     | 
| 
      
 105 
     | 
    
         
            +
                # The same as `pack_hexdigest(digest(obj))`.
         
     | 
| 
      
 106 
     | 
    
         
            +
                #
         
     | 
| 
      
 107 
     | 
    
         
            +
                # obj - A JSON serializable object.
         
     | 
| 
      
 108 
     | 
    
         
            +
                #
         
     | 
| 
      
 109 
     | 
    
         
            +
                # Returns a String digest of the object.
         
     | 
| 
      
 110 
     | 
    
         
            +
                def hexdigest(obj)
         
     | 
| 
      
 111 
     | 
    
         
            +
                  build_digest(obj).hexdigest!
         
     | 
| 
      
 112 
     | 
    
         
            +
                end
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                # Internal: Pack a binary digest to a hex encoded string.
         
     | 
| 
      
 115 
     | 
    
         
            +
                #
         
     | 
| 
      
 116 
     | 
    
         
            +
                # bin - String bytes
         
     | 
| 
      
 117 
     | 
    
         
            +
                #
         
     | 
| 
      
 118 
     | 
    
         
            +
                # Returns hex String.
         
     | 
| 
      
 119 
     | 
    
         
            +
                def pack_hexdigest(bin)
         
     | 
| 
      
 120 
     | 
    
         
            +
                  bin.unpack('H*'.freeze).first
         
     | 
| 
      
 121 
     | 
    
         
            +
                end
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                # Internal: Unpack a hex encoded digest string into binary bytes.
         
     | 
| 
      
 124 
     | 
    
         
            +
                #
         
     | 
| 
      
 125 
     | 
    
         
            +
                # hex - String hex
         
     | 
| 
      
 126 
     | 
    
         
            +
                #
         
     | 
| 
      
 127 
     | 
    
         
            +
                # Returns binary String.
         
     | 
| 
      
 128 
     | 
    
         
            +
                def unpack_hexdigest(hex)
         
     | 
| 
      
 129 
     | 
    
         
            +
                  [hex].pack('H*')
         
     | 
| 
      
 130 
     | 
    
         
            +
                end
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
                # Internal: Pack a binary digest to a base64 encoded string.
         
     | 
| 
      
 133 
     | 
    
         
            +
                #
         
     | 
| 
      
 134 
     | 
    
         
            +
                # bin - String bytes
         
     | 
| 
      
 135 
     | 
    
         
            +
                #
         
     | 
| 
      
 136 
     | 
    
         
            +
                # Returns base64 String.
         
     | 
| 
      
 137 
     | 
    
         
            +
                def pack_base64digest(bin)
         
     | 
| 
      
 138 
     | 
    
         
            +
                  [bin].pack('m0')
         
     | 
| 
      
 139 
     | 
    
         
            +
                end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                # Internal: Pack a binary digest to a urlsafe base64 encoded string.
         
     | 
| 
      
 142 
     | 
    
         
            +
                #
         
     | 
| 
      
 143 
     | 
    
         
            +
                # bin - String bytes
         
     | 
| 
      
 144 
     | 
    
         
            +
                #
         
     | 
| 
      
 145 
     | 
    
         
            +
                # Returns urlsafe base64 String.
         
     | 
| 
      
 146 
     | 
    
         
            +
                def pack_urlsafe_base64digest(bin)
         
     | 
| 
      
 147 
     | 
    
         
            +
                  str = pack_base64digest(bin)
         
     | 
| 
      
 148 
     | 
    
         
            +
                  str.tr!('+/'.freeze, '-_'.freeze)
         
     | 
| 
      
 149 
     | 
    
         
            +
                  str.tr!('='.freeze, ''.freeze)
         
     | 
| 
      
 150 
     | 
    
         
            +
                  str
         
     | 
| 
      
 151 
     | 
    
         
            +
                end
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                # Internal: Maps digest class to the CSP hash algorithm name.
         
     | 
| 
      
 154 
     | 
    
         
            +
                HASH_ALGORITHMS = {
         
     | 
| 
      
 155 
     | 
    
         
            +
                  Digest::SHA256 => 'sha256'.freeze,
         
     | 
| 
      
 156 
     | 
    
         
            +
                  Digest::SHA384 => 'sha384'.freeze,
         
     | 
| 
      
 157 
     | 
    
         
            +
                  Digest::SHA512 => 'sha512'.freeze
         
     | 
| 
      
 158 
     | 
    
         
            +
                }
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
                # Public: Generate hash for use in the `integrity` attribute of an asset tag
         
     | 
| 
      
 161 
     | 
    
         
            +
                # as per the subresource integrity specification.
         
     | 
| 
      
 162 
     | 
    
         
            +
                #
         
     | 
| 
      
 163 
     | 
    
         
            +
                # digest - The String byte digest of the asset content.
         
     | 
| 
      
 164 
     | 
    
         
            +
                #
         
     | 
| 
      
 165 
     | 
    
         
            +
                # Returns a String or nil if hash algorithm is incompatible.
         
     | 
| 
      
 166 
     | 
    
         
            +
                def integrity_uri(digest)
         
     | 
| 
      
 167 
     | 
    
         
            +
                  case digest
         
     | 
| 
      
 168 
     | 
    
         
            +
                  when Digest::Base
         
     | 
| 
      
 169 
     | 
    
         
            +
                    digest_class = digest.class
         
     | 
| 
      
 170 
     | 
    
         
            +
                    digest = digest.digest
         
     | 
| 
      
 171 
     | 
    
         
            +
                  when String
         
     | 
| 
      
 172 
     | 
    
         
            +
                    digest_class = DIGEST_SIZES[digest.bytesize]
         
     | 
| 
      
 173 
     | 
    
         
            +
                  else
         
     | 
| 
      
 174 
     | 
    
         
            +
                    raise TypeError, "unknown digest: #{digest.inspect}"
         
     | 
| 
      
 175 
     | 
    
         
            +
                  end
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                  if hash_name = HASH_ALGORITHMS[digest_class]
         
     | 
| 
      
 178 
     | 
    
         
            +
                    "#{hash_name}-#{pack_base64digest(digest)}"
         
     | 
| 
      
 179 
     | 
    
         
            +
                  end
         
     | 
| 
      
 180 
     | 
    
         
            +
                end
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
                # Public: Generate hash for use in the `integrity` attribute of an asset tag
         
     | 
| 
      
 183 
     | 
    
         
            +
                # as per the subresource integrity specification.
         
     | 
| 
      
 184 
     | 
    
         
            +
                #
         
     | 
| 
      
 185 
     | 
    
         
            +
                # digest - The String hexbyte digest of the asset content.
         
     | 
| 
      
 186 
     | 
    
         
            +
                #
         
     | 
| 
      
 187 
     | 
    
         
            +
                # Returns a String or nil if hash algorithm is incompatible.
         
     | 
| 
      
 188 
     | 
    
         
            +
                def hexdigest_integrity_uri(hexdigest)
         
     | 
| 
      
 189 
     | 
    
         
            +
                  integrity_uri(unpack_hexdigest(hexdigest))
         
     | 
| 
      
 190 
     | 
    
         
            +
                end
         
     | 
| 
      
 191 
     | 
    
         
            +
             
     | 
| 
      
 192 
     | 
    
         
            +
                private
         
     | 
| 
      
 193 
     | 
    
         
            +
                  def build_digest(obj)
         
     | 
| 
      
 194 
     | 
    
         
            +
                    digest = digest_class.new
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                    ADD_VALUE_TO_DIGEST[obj.class].call(obj, digest)
         
     | 
| 
      
 197 
     | 
    
         
            +
                    digest
         
     | 
| 
      
 198 
     | 
    
         
            +
                  end
         
     | 
| 
      
 199 
     | 
    
         
            +
              end
         
     | 
| 
      
 200 
     | 
    
         
            +
            end
         
     |