module Jekyll module Assets module Liquid class Tag < ::Liquid::Tag require_relative "tag/proxied_asset" require_relative "tag/parser" attr_reader :args class AssetNotFoundError < StandardError def initialize(asset) super "Could not find the asset `#{asset}'" end end # --------------------------------------------------------------------- Tags = { "css" => %Q{<link type="text/css" rel="stylesheet" href="%s"%s>}, "js" => %Q{<script type="text/javascript" src="%s"%s></script>}, "img" => %Q{<img src="%s"%s>} } # --------------------------------------------------------------------- Alias = { "image" => "img", "stylesheet" => "css", "javascript" => "js", "style" => "css" } # --------------------------------------------------------------------- def initialize(tag, args, tokens) @tokens = tokens @tag = from_alias(tag) @args = Parser.new(args, @tag) @og_tag = tag super end # --------------------------------------------------------------------- # NOTE: We only attach to the regenerator if you are using digested # assets, otherwise we forego any association with it so that we keep # your builds ultra fast, this is ideal in dev. Disable digests and # let us process independent so the entire site isn't regenerated # because of a single asset change. # --------------------------------------------------------------------- def render(context) site = context.registers.fetch(:site) page = context.registers.fetch(:page, {}).fetch("path", nil) sprockets = site.sprockets asset = find_asset(sprockets) add_as_jekyll_dependency(site, sprockets, page, asset) process_tag(sprockets, asset) rescue => e capture_and_out_error \ site, e end # --------------------------------------------------------------------- private def from_alias(tag) Alias.has_key?(tag) ? Alias.fetch(tag) : tag end # --------------------------------------------------------------------- private def process_tag(sprockets, asset) sprockets.used.add(asset) unless @tag == "asset_source" set_img_alt asset if @tag == "img" out = get_path sprockets, asset if @tag == "asset_path" return out elsif @tag == "asset" || @tag == "asset_source" return asset.to_s elsif @args.has_key?(:data) && @args.fetch(:data).has_key?(:uri) return Tags.fetch(@tag) % [ asset.data_uri, @args.to_html ] else return Tags.fetch(@tag) % [ out, @args.to_html ] end end # --------------------------------------------------------------------- private def get_path(sprockets, asset) sprockets.prefix_path(sprockets.digest?? asset.digest_path : asset.logical_path) end # --------------------------------------------------------------------- private def set_img_alt(asset) if !@args.has_key?(:html) || !@args.fetch(:html).has_key?("alt") @args.fetch_or_store(:html, {}).store("alt", asset.logical_path) end end # --------------------------------------------------------------------- private def add_as_jekyll_dependency(site, sprockets, page, asset) if page && sprockets.digest? site.regenerator.add_dependency( site.in_source_dir(page), site.in_source_dir(asset.logical_path) ) end end # --------------------------------------------------------------------- private def find_asset(sprockets) file, _sprockets = @args.fetch(:file), @args.fetch(:sprockets, {}) if !(out = sprockets.find_asset(file, _sprockets)) raise AssetNotFoundError, @args.fetch(:file) else out.liquid_tags << self !args.has_proxies?? out : ProxiedAsset.new(out, \ @args, sprockets, self) end end # --------------------------------------------------------------------- # There is no guarantee that Jekyll will pass on the error for some # reason (unless you are just booting up) so we capture that error and # always output it, it can lead to some double errors but I would # rather there be a double error than no error. # --------------------------------------------------------------------- private def capture_and_out_error(site, error) if error.is_a?(Sass::SyntaxError) file = error.sass_filename.gsub(/#{Regexp.escape(site.source)}\//, "") Jekyll.logger.error(%Q{Error in #{file}:#{error.sass_line} #{error}}) else Jekyll.logger.error \ "", error.to_s end raise error end end end end end %W(js css img image javascript stylesheet style asset_path asset_source asset).each do |tag| Liquid::Template.register_tag tag, Jekyll::Assets::Liquid::Tag end