class KdbookBin

Public Instance Methods

build(*files) click to toggle source
# File bin/kdbook, line 48
def build(*files)
  puts "BUILD REQUEST IN FOR FILES: #{files}".yellow if DEBUG
  file_list(options).each do |file|
    file.output.each do |out|
      puts "files: #{files}" if DEBUG
      puts "file: #{file}" if DEBUG
      if DEBUG && build?(files, file)
        puts 'It _IS_ a build '.blue
      else
        puts 'It is not a build '.blue
      end
      next unless build?(files, file)
      case out
      when /pdf/i
        to_pdf(file.input, output_file(file.input, out))
      when /html/i
        to_html(file.input, output_file(file.input, out), file.template)
      else
        puts "Output format '#{out}' is unsupported!".red
      end
    end
  end
end
clean() click to toggle source
# File bin/kdbook, line 73
def clean
  output_file_list(options).each do |f|
    puts "Cleaning file '#{f}'".blue
    File.delete(f) if File.exists?(f)
    puts "Failed to remove file '#{f}'" if File.exists?(f)
  end
end
gen_config() click to toggle source
# File bin/kdbook, line 87
def gen_config
  if File.exists?(options[:'config-file'])
    confirm_write(options)
  else
    write_default_file(options)
  end
end
serve() click to toggle source
# File bin/kdbook, line 104
  def serve
    files = options[:files]
    files = output_file_list(options) if files.empty?
    interface = options[:interface]
    port = options[:port]
    build = options[:build]
    do_build = method(:build)

    require 'sinatra'

    kdbook_server = Class.new(Sinatra::Base)
    kdbook_server.set(:bind, interface)
    kdbook_server.set(:port, port)

    kdbook_server.get('/') do
      # show an index with links to all the files
      <<DOC
        <!DOCTYPE html>
        <html>
        <head>
          <title>kdbook list of files</title>
        </head>
        <body>
          <p><strong>kdbook list of files:</strong></p>
          <ul>
      #{files.map{|f| "<li><a href=\"#{f}\">#{f}</a></li>"}.join(' ') }
          </ul>
        </body>
        </html>
DOC
    end

    kdbook_server.get('/:filename') do |filename|
      puts "Received request for file '#{filename}'".green
      if build
        puts "Building all files fresh before responding".green
        do_build.call(filename)
        puts "Done building".green
      else
        puts "Not building before serving cause build is disabled".yellow
      end

      if File.exist?(filename)
        puts "File '#{filename}' found.  serving...".green
        send_file(filename)
      else
        puts "File '#{filename}' not found.  Check URL and make sure files are built.  Returning 404".red
        halt 404
      end
    end

    puts "Starting the server on port #{options[:port]}.".green
    kdbook_server.run!
    puts 'Server has exited.'.green
  end
version() click to toggle source
# File bin/kdbook, line 37
def version
  puts "Kdbook - Version: #{VERSION}"
end
wordcount() click to toggle source
# File bin/kdbook, line 21
def wordcount
  file_list(options).each do |inp|
    if inp.wordcount
      wc = rm_non_words(read_file(inp.input)).split(' ').length
      output = "Wordcount of #{inp.input} is #{add_commas(wc)}"
      if inp.wordcount.is_a?(RecursiveOpenStruct) && inp.wordcount.min
        output = "#{output}.  #{percentify(wc, inp.wordcount.min)}% " \
                 "of goal #{inp.wordcount.min}"
        output = "#{output} to #{inp.wordcount.max}" if inp.wordcount.max
      end
      puts output.green
    end
  end
end

Private Instance Methods

add_commas(number) click to toggle source
# File bin/kdbook, line 260
def add_commas(number)
  number.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
end
add_missing_output(file) click to toggle source
# File bin/kdbook, line 281
def add_missing_output(file)
  file[:output] = %w[html pdf] unless file[:output]
  file
end
build?(files, file) click to toggle source
# File bin/kdbook, line 293
def build?(files, file)
  return true if files.empty?
  files.include?(file.input) || files.include?(file.output) || files.any? do |f|
    file.input.include?(f) || file.output.include?(f)
  end
end
config(options) click to toggle source
# File bin/kdbook, line 286
def config(options)
  config_file_contents(options)
    .map { |f| upgrade_file_string(f) }
    .map { |f| add_missing_output(f) }
    .map { |f| RecursiveOpenStruct.new(f, recurse_over_arrays: true) }
end
config_file_comments() click to toggle source
# File bin/kdbook, line 162
def config_file_comments
  %q(---
    # array of: either just a string (input file), a hash
    # with input (which is input filename), optional output
    # formats, optional template file for HTML, optional
    # flag to count toward word count (defaults to true if
    # not specified).  Example entry in array:
    #
    # kdbook:
    # - input: 'main-book.md'
    #   output: ['html', 'pdf']
    #   wordcount:
    #     min: 60000
    #     max: 90000
    #).split("\n").map{|s| s.sub(' ' * 6, '')}.join("\n")
end
config_file_contents(options) click to toggle source
# File bin/kdbook, line 268
def config_file_contents(options)
  if File.exists?(options[:'config-file'])
    YAML.load_file(options[:'config-file'])['kdbook']
  else
    # pass a straight array of filenames in the current dir name *.md
    Dir.glob('*.md')
  end
end
config_file_defaults() click to toggle source
# File bin/kdbook, line 179
def config_file_defaults
  {
    'output' => ['html', 'pdf'],
    'wordcount' => { 'min' => 60000, 'max' => 90000 }
  }
end
confirm_write(options) click to toggle source
# File bin/kdbook, line 200
def confirm_write(options)
  print "A config file already exists at #{options[':config-file']}.  Overwrite?  (Y/N): ".yellow
  action = STDIN.gets.chomp
  if action =~ /y/i
    puts "Overwriting config file with new version at #{options[:'config-file']}".green
    write_default_file(options)
  else
    puts "User declined.  Not writing config file".red
    return
  end
end
file_list(options) click to toggle source
# File bin/kdbook, line 212
def file_list(options)
  config(options)
end
input_file_list(options) click to toggle source
# File bin/kdbook, line 216
def input_file_list(options)
  file_list(options).map(&:input)
end
output_file(input_file, out_format) click to toggle source
# File bin/kdbook, line 220
def output_file(input_file, out_format)
  input_file.gsub(/md$/, out_format)
end
output_file_list(options) click to toggle source
# File bin/kdbook, line 228
def output_file_list(options)
  file_list(options).map{ |file| output_files(file.input, file.output) }.flatten
end
output_files(input_file, out_formats) click to toggle source
# File bin/kdbook, line 224
def output_files(input_file, out_formats)
  out_formats.map{ |out| output_file(input_file, out) }
end
percentify(num, den) click to toggle source
# File bin/kdbook, line 264
def percentify(num, den)
  ((num.to_f / den.to_f) * 100.0).round(2)
end
read_file(file) click to toggle source
# File bin/kdbook, line 240
def read_file(file)
  rm_hidden_comments(File.read(file))
end
rm_hidden_comments(input) click to toggle source
# File bin/kdbook, line 232
def rm_hidden_comments(input)
  input.gsub(/\/--.*?--\//m, "")
end
rm_non_words(input) click to toggle source
# File bin/kdbook, line 236
def rm_non_words(input)
  input.split("\n").select { |line| !(line =~ /^\s*#/) }.join("\n")
end
to_html(inp, out, template = nil) click to toggle source
# File bin/kdbook, line 250
def to_html(inp, out, template = nil)
  puts "Generating #{out}".blue
  k = if template
        Kramdown::Document.new(read_file(inp), template: template)
      else
        Kramdown::Document.new(read_file(inp))
      end
  File.write(out, k.to_html)
end
to_pdf(inp, out) click to toggle source
# File bin/kdbook, line 244
def to_pdf(inp, out)
  puts "Generating #{out}".blue
  k = Kramdown::Document.new(read_file(inp))
  File.write(out, k.to_pdf)
end
upgrade_file_string(file) click to toggle source
# File bin/kdbook, line 277
def upgrade_file_string(file)
  file.is_a?(String) ? { input: file } : file
end
write_default_file(options) click to toggle source
# File bin/kdbook, line 186
def write_default_file(options)
  comments = config_file_comments
  defaults = config_file_defaults
  glob = Dir.glob('*.md')
  puts "Writing config file to '#{options[:'config-file']}' containing files: #{glob.join(', ')}".green
  yaml = { 'kdbook' => glob
    .map{ |f| { 'input' => f }
    .merge(defaults) }}
  File.write(
    options[:'config-file'],
    yaml.to_yaml.gsub('---', comments)
  )
end