module Gumdrop

The simple and sweet static CMS! (and prototyping tool)

require ‘ostruct’

Constants

DEFAULT_CONFIG
JETSAM_FILES
LOG_LEVELS
STATIC_ASSETS
VERSION
WEB_PAGE_EXTS

Public Class Methods

blacklist(*paths) click to toggle source

Specified paths will not be rendered to output (matching against the source tree).

# File lib/gumdrop/site.rb, line 366
def blacklist(*paths)
  paths.each do |path|
    if path.is_a? Array
      config.blacklist.concat path
    else
      config.blacklist << path
    end
  end      
end
build(opts={}) click to toggle source
# File lib/gumdrop/builder.rb, line 144
def build(opts={})
  opts= opts.to_symbolized_hash
  site.scan
  Builder.new(opts).execute
end
change_log() click to toggle source

Returns ‘ChangeLog.md’ from gem package.

# File lib/gumdrop.rb, line 36
def self.change_log
  here= File.dirname(__FILE__)
  File.read here / ".." / "ChangeLog.md"
end
cli(&block) click to toggle source

Allows addition of CLI commands from Gumdrop file:

Gumdrop.cli do
  desc 'ping'
  method_option :loud, default:false
  def ping
    say options[:loud] ? 'PONG!' : 'pong'
  end
end
# File lib/gumdrop/cli.rb, line 15
def cli(&block)
  CLI::Internal.class_eval &block
end
config() click to toggle source

Short cut to the current Site config object.

# File lib/gumdrop/site.rb, line 331
def config
  site.config
end
configure(&block) click to toggle source

Yield a configuration object. You can update Gumdrop behavior as well as add your own config information.

# File lib/gumdrop/site.rb, line 322
def configure(&block)
  site.configure &block
end
env() click to toggle source

The env Gumdrop is run in – You can set this in the config or, better, via command line: ‘gumdrop build -e test`

# File lib/gumdrop/site.rb, line 337
def env
  site.env
end
generate(name=nil, opts={}, &block) click to toggle source

Generate a page (based on data or whatever) from your Gumdrop file like this:

Gumdrop.generate 'label' do |gen|
  gen.file 'my-page.html' do
    # whatever you return is set as the page contents.
    "hello!"
  end
end
# File lib/gumdrop/generator.rb, line 140
def generate(name=nil, opts={}, &block)
  opts[:filename]= name unless opts[:filename]
  site.generators << Generator.new(nil, opts, &block)
end
handle_proxy(proxy, proxy_url, env) click to toggle source
# File lib/gumdrop/util/proxy_handler.rb, line 26
def self.handle_proxy(proxy, proxy_url, env)
  if proxy[:secure] && !HTTPS_ENABLED
    log.warn "~ WARNING: HTTPS is not supported on your system, using HTTP instead.\n"
    log.warn "   If you are using Ubuntu, you can run `apt-get install libopenssl-ruby`\n"
    proxy[:secure] = false
  end

  origin_host = env['SERVER_NAME'] # capture the origin host for cookies
  http_method = env['REQUEST_METHOD'].to_s.downcase
  url = proxy[:path_info] #proxy_url #env['PATH_INFO']
  params = env['QUERY_STRING']
  
  log.info "PROXY: -> #{url}"

  # collect headers...
  headers = {}
  env.each do |key, value|
    next unless key =~ /^HTTP_/
    key = key.gsub(/^HTTP_/,'').downcase.sub(/^\w/){|l| l.upcase}.gsub(/_(\w)/){|l| "-#{$1.upcase}"} # remove HTTP_, dasherize and titleize
    if !key.eql? "Version"
      headers[key] = value
    end
  end

  # Rack documentation says CONTENT_TYPE and CONTENT_LENGTH aren't prefixed by HTTP_
  headers['Content-Type'] = env['CONTENT_TYPE'] if env['CONTENT_TYPE']

  length = env['CONTENT_LENGTH']
  headers['Content-Length'] = length if length

  http_host, http_port = proxy[:to].split(':')
  http_port = proxy[:secure] ? '443' : '80' if http_port.nil?

  # added 4/23/09 per Charles Jolley, corrects problem
  # when making requests to virtual hosts
  headers['Host'] = "#{http_host}:#{http_port}"

  if proxy[:url]
    url = url.sub(/^#{Regexp.escape proxy_url}/, proxy[:url])
  end

  http_path = [url]
  http_path << params if params && params.size>0
  http_path = http_path.join('?')

  response = nil
  no_body_method = %w(get copy head move options trace)

  done = false
  tries = 0
  until done
    http = ::Net::HTTP.new(http_host, http_port)

    if proxy[:secure]
      http.use_ssl = true
      http.verify_mode = OpenSSL::SSL::VERIFY_NONE
    end

    http.start do |web|
      if no_body_method.include?(http_method)
        response = web.send(http_method, http_path, headers)
      else
        http_body = env['rack.input']
        http_body.rewind # May not be necessary but can't hurt

        req = Net::HTTPGenericRequest.new(http_method.upcase,
                                            true, true, http_path, headers)
        req.body_stream = http_body if length.to_i > 0
        response = web.request(req)
      end
    end

    status = response.code # http status code
    protocol = proxy[:secure] ? 'https' : 'http'

    log.info "~ PROXY: #{http_method.upcase} #{status} #{url} -> #{protocol}://#{http_host}:#{http_port}#{http_path}\n"

    # display and construct specific response headers
    response_headers = {}
    ignore_headers = ['transfer-encoding', 'keep-alive', 'connection']
    response.each do |key, value|
      next if ignore_headers.include?(key.downcase)
      # If this is a cookie, strip out the domain.  This technically may
      # break certain scenarios where services try to set cross-domain
      # cookies, but those services should not be doing that anyway...
      value.gsub!(/domain=[^\;]+\;? ?/,'') if key.downcase == 'set-cookie'
      # Location headers should rewrite the hostname if it is included.
      value.gsub!(/^http:\/\/#{http_host}(:[0-9]+)?\//, "http://#{http_host}/") if key.downcase == 'location'
      # content-length is returning char count not bytesize
      if key.downcase == 'content-length'
        if response.body.respond_to?(:bytesize)
          value = response.body.bytesize.to_s
        elsif response.body.respond_to?(:size)
          value = response.body.size.to_s
        else
          value = '0'
        end
      end

      #$stderr << "   #{key}: #{value}\n"

      response_headers[key] = value
    end

    if [301, 302, 303, 307].include?(status.to_i) && proxy[:redirect] != false
      log.warn '~ REDIRECTING: '+response_headers['location']+"\n"

      uri = URI.parse(response_headers['location']);
      http_host = uri.host
      http_port = uri.port
      http_path = uri.path
      http_path += '?'+uri.query if uri.query

      tries += 1
      if tries > 10
        raise "Too many redirects!"
      end
    else
      done = true
    end
  end

  # Thin doesn't like null bodies
  response_body = response.body || ''
  #::Rack::Utils::HeaderHash.new(response_headers)
  return [status.to_i, response_headers, response_body.to_s]
end
ignore(*paths) click to toggle source

Specified paths will be added to the ignore list, preventing matching files from appearing in the source tree

# File lib/gumdrop/site.rb, line 354
def ignore(*paths)
  paths.each do |path|
    if path.is_a? Array
      config.ignore.concat path
    else
      config.ignore << path
    end
  end      
end
in_site_folder?(filename="Gumdrop") click to toggle source

Returns true if this, or a parent, folder has a Gumdrop file.

# File lib/gumdrop/site.rb, line 348
def in_site_folder?(filename="Gumdrop")
  !fetch_site_file(filename).nil?
end
init_logging() click to toggle source
# File lib/gumdrop/util/loggable.rb, line 32
def init_logging
  level= (site.config.log_level || :warn).to_sym
  @log = Logger.new site.config.log || STDOUT
  @log.level=  LOG_LEVELS[level]
  # @log.formatter = proc { |severity, datetime, progname, msg|
  #   # original_formatter.call(severity, datetime, progname, msg.dump)
  #   "#{msg}\n"
  # }
end
log() click to toggle source
# File lib/gumdrop/util/loggable.rb, line 24
def log
  @log ||= begin
    log= Logger.new STDOUT
    log.level= LOG_LEVELS[:warn]
    log
  end
end
mode() click to toggle source

Mostly for internal use, but you can update/change it in the configure block.

# File lib/gumdrop/site.rb, line 343
def mode
  site.mode
end
no_render(*paths) click to toggle source

Specified paths will be treated as binary files and copied, not rendered.

# File lib/gumdrop/site.rb, line 378
def no_render(*paths)
  paths.each do |path|
    if path.is_a? Array
      config.no_render.concat path
    else
      config.no_render << path
    end
  end      
end
on(event_type, options={}, &block) click to toggle source

Listen for life-cycle events in your Gumdrop file like this:

Gumdrop.on :start do |event|
  puts "Here we go!"
end

Complete list of events fired by Gumdrop:

:start
:before_scan
:scan
:after_scan
:before_generate
:generate
:after_generate
:before_generate_item
:generate_item
:after_generate_item
:before_build
:build
:after_build
:before_checksum
:checksum
:after_checksum
:before_render
:render
:after_render
:before_render_item
:render_item
:after_render_item
:before_write
:write
:after_write
:before_copy_file
:copy_file
:after_copy_file
:before_write_file
:write_file
:after_write_file
:end

In the block parem ‘event` you will have access to :site, the current executing site instance, and :payload, where applicable.

:render_item is a special event because you can add/override the compiled output by modifying ‘event.data.return_value`

# File lib/gumdrop/site.rb, line 316
def on(event_type, options={}, &block)
  site.on event_type, options, &block
end
prepare(&block) click to toggle source
# File lib/gumdrop/site.rb, line 326
def prepare(&block)
  site.prepare &block
end
read_me() click to toggle source

Returns ‘ReadMe.md’ from gem package.

# File lib/gumdrop.rb, line 42
def self.read_me
  here= File.dirname(__FILE__)
  File.read here / ".." / "ReadMe.md"
end
rebuild() click to toggle source
# File lib/gumdrop/builder.rb, line 150
def rebuild
  site.scan true
  Builder.new.execute
end
run(opts={}) click to toggle source

Kicks off the build process!

# File lib/gumdrop/builder.rb, line 156
def run(opts={})
  opts= opts.to_symbolized_hash
  site.options= opts
  Gumdrop.build opts
end
site(opts={}, force_new=false) click to toggle source

This will look for a nearby Gumdrop file and load the Site the first time it is called. Each time after it will just return the already created Site.

# File lib/gumdrop/site.rb, line 254
def site(opts={}, force_new=false)
  opts= opts.to_symbolized_hash
  unless @current_site.nil? or force_new
    @current_site.options= opts unless opts.empty?
    @current_site
  else
    site_file= fetch_site_file
    unless site_file.nil?
      Site.new site_file, opts
    else
      nil
    end
  end
end
view_helpers(&block) click to toggle source
# File lib/gumdrop/util/view_helpers.rb, line 79
def view_helpers(&block)
  Util::ViewHelpers.class_eval &block
end

Protected Class Methods

fetch_site_file(filename="Gumdrop") click to toggle source

Walks up the filesystem, starting from Dir.pwd, looking for a Gumdrop file. Returns nil if not found.

# File lib/gumdrop/site.rb, line 392
def fetch_site_file(filename="Gumdrop")
  here= Dir.pwd
  found= File.file?  here / filename
  # TODO: Should be smarter -- This is a hack for Windows support "C:\"
  while !found and File.directory?(here) and File.dirname(here).length > 3
    here= File.expand_path here /'..'
    found= File.file?  here / filename
  end
  if found
    File.expand_path here / filename
  else
    nil
  end
end
set_current_site(site) click to toggle source
# File lib/gumdrop/site.rb, line 407
def set_current_site(site)
  @current_site= site
end