module Plate # An asset is a dynamic stylesheet or javascript file that needs some processing before it is ready # to be placed into the site's destination directory. # # Some examples of supported asset formats are [CoffeeScript](http://coffeescript.org) # and [Sass](http://sass-lang.com). # # # Asset Engines # # Assets are compiled based on the file extensions of the source file, and the so-called "engines" # that are available and registered to Plate. By default, Plate does not require any of these # asset engines to run, so any external dependencies will need to be installed before attempting # to use an asset engine. # # For example, in order to use the CoffeeScript engine (and thus a file with the extension of # `.coffee`) the CoffeeScript gem will need to be installed. (`gem install coffee-script`). # # # File Naming # # For best results, name your source files exactly how you would like them to be displayed # once compiled. # # To create a file in the destination named site.js that is compiled from a CoffeeScript source, # name the file in the source directory site.js.coffee. The asset compilation engine will # stop trying to render the file with an asset engine when it finds the first non-registered # file extension. In this case, "js" is not recognized as an asset engine extension that needs # compilation, so compilation stops and the file is written to the destination. class Asset < Page def base_path assets_dir = File.join(self.site.source, 'assets') if self.file.start_with?(assets_dir) Pathname.new(File.join(self.site.source, 'assets')) else Pathname.new(File.join(self.site.source, 'content')) end end # The engines in use for this asset. Engines are determined by looping through # the extensions of the base file and associating those with a registered engine. # # @return [Array] List of engines in use for this file. def engines @engines ||= self.extensions.reverse.collect { |e| self.site.registered_asset_engines[e.gsub(/\./, '').to_sym] }.reject { |e| !e } end # The file extensions for this asset's source file. # # @return [Array] List of extensions def extensions @extensions ||= self.basename.scan(/\.[^.]+/) end # The end result format for this file. This is the first file extension in the asset's # source file name that is not a registered engine extension. # # For example, a file named `desktop.css.css` will have a format extension of "css". # # @return [String] def format_extension self.extensions.reverse.detect { |e| !self.site.asset_engine_extensions.include?(e) } end # The destination file path for this asset. # # @return [String] def file_path [ directory, file_name ].join('/') end # Directory name for the source asset file # # @return [String] def pathname File.dirname(self.file) end # Generates the resulting content for this asset using the `engines` determined # by the source file's name. Unlike a page, assets do not render content # using a layout. # # @return [String] def rendered_content return @rendered_content if @rendered_content around_callback :render do result = File.read(file) self.engines.each do |engine| template = engine.new() { result } result = template.render(self, :site => self.site) end @rendered_content = result end @rendered_content end # Write this asset file to the destination. The content is written to disk using the path # designated in {#file_path} and the content from {#rendered_content}. # # The callbacks `before_write` and `after_write` are included here. To perform # custom actions before or after an asset file is written to disk, use these callback # methods. # # See {Plate::Callbacks} for more information on setting up callbacks. # # @return [String] The file path that was written to. def write! path = File.join(site.build_destination, file_path) FileUtils.mkdir_p(File.dirname(path)) around_callback :write do File.open(path, 'w') do |f| f.write(self.rendered_content) end end path end end end