Module: Jekyll::DistorteD::StaticState

Included in:
Invoker
Defined in:
lib/distorted-jekyll/static_state.rb

Overview

This module implements the methods our tag needs in order to pretend to be a Jekyll::StaticFile so we don’t need to redundantly re-implement a Generator and Jekyll::Cleaner.

Constant Summary collapse

ATTRIBUTES =
Set[:title]

Instance Method Summary collapse

Instance Method Details

#destination(dest_root) ⇒ Object

Returns the to-be-written path of a single standard StaticFile. The value returned by this method is only the ‘main’ or ‘original’ (even if modified somehow) file and does not include the path/filenames of any variations. This method will be called by jekyll/lib/cleaner#new_files to generate the list of files that need to be build or rebuilt for a site. For this reason, this method shouldn’t do any kind of checking the real filesystem, since e.g. its URL-based destdir might not exist yet if the Site.dest is completely blank.



29
30
31
# File 'lib/distorted-jekyll/static_state.rb', line 29

def destination(dest_root)
  File.join(dest_root, @relative_dest, @name)
end

#destinations(dest_root) ⇒ Object

This method will be called by our monkey-patched Jekyll::Cleaner#new_files in place of the single-destination method usually used. This allows us to tell Jekyll about more than a single file that should be kept when regenerating the site. This makes DistorteD fast!



38
39
40
# File 'lib/distorted-jekyll/static_state.rb', line 38

def destinations(dest_root)
  wanted_files.map{|f| File.join(dest_root, @relative_dest, f)}
end

#modified?Boolean

HACK HACK HACK Jekyll does not pass this method a site.dest like it does write() and others, but I want to be able to short-circuit here if all the to-be-generated files already exist.

Returns:

  • (Boolean)


46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/distorted-jekyll/static_state.rb', line 46

def modified?
  # Assume modified for the sake of freshness :)
  modified = true

  site_dest = Jekyll::DistorteD::Floor::config(:destination).to_s
  if Dir.exist?(site_dest)
    if Dir.exist?(File.join(site_dest, @relative_dest))
      extant_files = Dir.entries(File.join(site_dest, @relative_dest)).to_set

      # TODO: Make this smarter. It's not enough that all the generated
      # filenames should exist. Try a few more ways to detect subtler
      # "changes to the source file since generation of variations.
      if wanted_files.subset?(extant_files)
        Jekyll.logger.debug(@name, "All variations present: #{wanted_files}")
        modified = false
      else
        Jekyll.logger.debug(@name, "Missing variations: #{wanted_files - extant_files}")
      end

    end  # relative_dest.exists?
  end  # site_dest.exists?
  Jekyll.logger.debug("#{@name} modified?",  modified)
  return modified
end

#write(dest_root) ⇒ Object

Write the static file to the destination directory (if modified).

dest - The String path to the destination dir.

Returns false if the file was not modified since last time (no-op).



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/distorted-jekyll/static_state.rb', line 87

def write(dest_root)
  plug
  return false if File.exist?(path) && !modified?

  # Create any directories to the depth of the intended destination.
  FileUtils.mkdir_p(File.join(dest_root, @relative_dest))
  # Save every desired variation of this image.
  # This will be a Set of Hashes each describing the name, type,
  # dimensions, attributes, etc of each output variation we want.
  # Full-size outputs will have the special tag `:full`.
  files.each { |variation|
    type = variation&.dig(:type)
    filename = File.join(dest_root, @relative_dest, variation&.dig(:name) || @name)

    if self.respond_to?(type.distorted_method)
      Jekyll.logger.debug("DistorteD::#{type.distorted_method}", filename)
      self.send(type.distorted_method, filename, **variation)
    elsif extname == ".#{type.preferred_extension}"
      Jekyll.logger.debug(@name, <<~RAWCOPY
          No #{type.distorted_method} method is defined,
          but the intended output type #{type.to_s} is the same
          as the input type, so I will fall back to copying the raw file.
        RAWCOPY
      )
      copy_file(filename)
    else
      Jekyll.logger.error(@name, "Missing rendering method #{type.distorted_method}")
      raise MediaTypeOutputNotImplementedError.new(filename, type, self.class.name)
    end
  }
end

#write?Boolean

Whether to write the file to the filesystem

Returns true unless the defaults for the destination path from _config.yml contain ‘published: false`.

Returns:

  • (Boolean)


75
76
77
78
79
80
# File 'lib/distorted-jekyll/static_state.rb', line 75

def write?
  publishable = defaults.fetch('published'.freeze, true)
  return publishable unless @collection

  publishable && @collection.write?
end