Skip to content
This repository
tree: 158149492f
Fetching contributors…

Cannot retrieve contributors at this time

file 208 lines (189 sloc) 6.828 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
require 'rake/clean'
require 'rubygems'
require 'hpricot'
require 'erb'

SOURCE_HTML = FileList['text/**/*.html']
WWW_HTML = FileList['output/**/**/*.html']
IMAGES = FileList['images/*']
OUTPUT_HTML = 'output/all.html'
CLOBBER.include('output','deb')

def template(filename,hash)
  ERB.new(File.open(filename).read).result(
    OpenStruct.new(hash).send(:binding)
  )
end

directory "output"

desc "Copy images to output directory"
task :images => :output
task :images => IMAGES do |t|
  IMAGES.each do |image|
    cp image, "output"
  end
end

desc "Combine source HTML into single HTML file"
task OUTPUT_HTML => [:output, :images]
file OUTPUT_HTML => SOURCE_HTML do |t|
  File.open(t.name,'w') do |out|
    SOURCE_HTML.sort.each do |source|
      out.puts File.open(source).read
    end
  end
end

file 'output/vim-recipes.pdf' => OUTPUT_HTML do |t|
  system("prince #{t.prerequisites.first} #{t.name}")
end

desc "Generate the PDF"
task :pdf => [:clobber, 'output/vim-recipes.pdf']

desc "Generate the Sitemap"
task :sitemap do
  sh "sitemap_gen.py --config=sitemap_config.xml --testing"
end

desc "Notify search engines about Sitemap"
task :sitemap_notify do
  sh "sitemap_gen.py --config=sitemap_config.xml"
end

def commit_time(file)
  Time.at(`git log -r --name-only --no-color --pretty=raw -z #{file}`.
       to_a.grep(/^committer/).last.match(/ (\d+) /)[1].to_i)
end

def make_toc
  toc = []
  section = 'Preliminaries'
  section_id = 'preliminaries'
  SOURCE_HTML.sort.each do |f|
    source = File.open(f).read
    doc = Hpricot(source)
    recipe_id = nil
    doc.search('h1, h2, h3, h4, h5, h6').each do |h_tag|
      title = h_tag ? h_tag.inner_text : 'Untitled'
      id = h_tag['id'] if h_tag
      next unless id && h_tag
      type = :subsection
      if h_tag.name == 'h2'
        section = title
        section_id = h_tag['id']
        type = :section
      elsif h_tag.name == 'h3'
        type = :recipe
        recipe_id = h_tag['id']
      end
      toc << { :id => h_tag['id'], :title => title, :file => f,
       :type => type, :section_name => section, :section_id => section_id,
       :recipe_id => recipe_id, :time => commit_time(f),
       :target_path => "output/#{section_id}/#{h_tag['id']}/index.html" }
    end
  end
  toc
end

desc "Generate the HTML version"
task :html => SOURCE_HTML do |t|
  toc = make_toc()
  toc.each_with_index do |entry,idx|
    next if entry[:type] == :subsection
    source = File.open(entry[:file]).read
    doc = Hpricot(source)

    if (entry[:type] == :section) || (entry[:id] == 'introduction')
        page = template('templates/chapter.html',
          {:title => entry[:id] == 'introduction' ? 'Preliminaries' : entry[:title],
           :recipes => toc.select do |e|
            (e[:section_id] == entry[:section_id]) &&
            (e[:type] == :recipe)
         end
        })
      path = "output/#{entry[:section_id]}/index.html"
      mkdir_p File.dirname(path)
      File.open(path,'w'){|f| f.puts page}
    end
    if entry[:type] == :recipe
      doc.search('h1, h2, h3, h4, h5, h6').each do |tag|
        new_tag = tag.name.sub(/(\d)/) {|m| m.to_i - 2}
        tag.swap("<#{new_tag} id='#{tag['id']}'>#{tag.inner_html}</#{new_tag}>")
      end
        
      doc.search('a[@href*=#]').each do |a|
        id = a['href'].sub(/^#/,'')
        sections = toc.select {|e| e[:id] == id}
        raise "Broken link (#{a}) in #{entry[:file]}" if sections.empty?
        next unless sections.size == 1
        sec = sections.first
        target = sec[:section_id] + '/' + id + '/'
        if sec[:type] == :subsection
          target = sec[:section_id] + '/' + sec[:recipe_id] + '/#' + sec[:id]
        end
        a.swap("<a href='/#{target}'>#{a.inner_html}</a>")
      end

      doc.search('img').each do |img|
        # FIXME: Awful hack: junks other attributes, assumes images to be in
        # root directory.
        img.swap("<img src='/#{img['src']}' />")
      end

      nxt = idx + 1 >= toc.size ? toc[0] : toc[(idx + 1)..-1].select{
        |e| e[:type] == :recipe}.first
      prv = idx == 0 ? toc[-1] : toc[0..(idx - 1)].select{
        |e| e[:type] == :recipe}[-1]
      page = template('templates/recipe.html',
        {:body => doc.to_s, :title => entry[:title], :id => entry[:id],
         :section_id => entry[:section_id], :section => entry[:section_name],
         :next_e => nxt, :prev_e => prv})
       #FIXME: Use :target_path instead:
       path = "output/#{entry[:section_id]}/#{entry[:id]}/index.html"
       mkdir_p File.dirname(path)
       File.open(path,'w') {|file| file.puts page}
       entry[:body] = doc.to_s
    end
  end
  page = template('templates/toc.html',
    {:toc => toc.dup.reject{|e| e[:type] == :subsection}})
  mkdir_p 'output/toc'
  File.open('output/toc/index.html','w') {|file| file.puts page}
  recipes_by_time = toc.reject{|e| e[:type] == :subsection}.
                        sort_by{|e| e[:time]}.reverse
  page = template('templates/atom.atom',
    {:toc => recipes_by_time, :updated => recipes_by_time.first[:time]})
  File.open('output/index.atom','w') {|file| file.puts page}
end

directory 'output/css'
desc "Generate the website"
task :www => ['output/vim-recipes.pdf',:html, 'output/css'] do
  FileList['www/*', 'www/.[a-z]*'].each {|f| cp f, 'output/'}
  File.open('output/css/style.css','w') do |merged|
    ['main','web'].each do |name|
      merged.print File.open('templates/' + name + '.css').read
    end
  end
  cp_r 'js', 'output/'
end

desc "Upload the website"
task :upload => [:www, :sitemap] do
  rm OUTPUT_HTML
  sh "rsync -vaz output/ vim.runpaint.org:/home/public/"
  Rake::Task['sitemap_notify'].invoke
  sh 'git push'
end

desc "Generate the .deb"
task :deb => [:www] do
  deb_dir = 'deb/usr/share/doc/vimrecipes'
  html_dir = deb_dir + '/html'
  mkdir_p html_dir
  cp 'output/toc/index.html', html_dir
  #sh "gzip -c output/vim-recipes.pdf >#{deb_dir}/vim-recipes.pdf.gz"
  FileList['output/*/','output/*.png'].each {|d| cp_r d, html_dir}
  FileList["#{html_dir}/*.html", "#{html_dir}/*/*.html",
           "#{html_dir}/*/*/*.html"].each do |file|
    prefix = '../' * (file.count('/') - html_dir.count('/') - 1)
    doc = Hpricot(File.open(file).read)
    doc.search('link[@rel=alternate]').remove
    doc.search('form, script, noscript').remove
    if doc.at('#disqus_thread')
      doc.at('#disqus_thread').after('<script src="/js/footnotes.js">')
    end
    %w{href src}.each do |attr|
      doc.search("*[@#{attr}]").each do |tag|
          next unless tag[attr].start_with? '/'
          tag[attr] = prefix + tag[attr][1..-1]
          tag[attr] += 'index.html' if tag[attr].end_with? '/'
          tag[attr] = tag[attr].sub('/toc','') || tag[attr]
      end
    end
    File.open(file,'w').puts doc
  end
end
Something went wrong with that request. Please try again.