#!/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby -wKU # == Synopsis # # gen_html: generates HTML file from markdown and optional template(s) # # == Usage # # gen_html [OPTION] ... [FILE] # # --help: # show help # # -t/--title «title» # make «title» available to template (as `page_name`) # # -h/--header «file» # prepend «file» as header (erb) # # -f/--footer «file» # append «file» as footer (erb) # # FILE: The markdown document to read (defaults to stdin) require 'getoptlong' require 'rdoc/usage' require 'erb' def expand_tpl(str, binding) ERB.new(str, 0, '%-<>').result(binding) end def expand_tpl_file(path, binding) expand_tpl(File.read(path), binding) end def find_exe(cmd) dir = ENV['PATH'].split(':').find { |dir| File.executable? File.join(dir, cmd) } dir ? "#{dir}/#{cmd}" : nil end def wrap_key_equivalents(src) src.gsub(/ `([^`]+⇥)` | \( ([⌃⌥⇧⌘↓↑←→]+) \) | ( [⎋⇥↩⌅⌫⌦] | [⌃⌥⇧⌘]+ ( (?=[ ]|-\w+) | F\d+ | . ) ) /x) do if $1 "#$1" elsif $2 "(#$2)" else "#$&" end end end def wrap_authors(src) src.gsub(/ \*\[ (.+?) \]\* /x) do "#$1" end end def wrap_in_article(html) html.gsub(/.*<\/h2>(?m:.*?)(?=\s*\n#$&\n\n" end end opts = GetoptLong.new( [ '--title', '-t', GetoptLong::REQUIRED_ARGUMENT ], [ '--header', '-h', GetoptLong::REQUIRED_ARGUMENT ], [ '--footer', '-f', GetoptLong::REQUIRED_ARGUMENT ], [ '--help', GetoptLong::NO_ARGUMENT ] ) title, header, footer = 'untitled', nil, nil opts.each do |opt, arg| case opt when '--help' RDoc::usage when '--header' header = arg when '--footer' footer = arg end end MARKDOWN_COMPILERS = %w[ multimarkdown ] filter = MARKDOWN_COMPILERS.find { |exe| find_exe exe } abort "Unable to find a markdown compiler" if filter.nil? filters = "|#{filter} --nosmart" document = ARGF.read document = wrap_authors(wrap_key_equivalents(document)) head, body = document.scan(/\A((?:^\w+:\s+.*$\n)*)\n?((?m:.*))\z/).flatten tmp = head.scan(/^(\w+):\s+(.*)$/).collect { |pair| [pair[0].downcase, pair[1].strip] } headers = Hash[*tmp.flatten] page_title = headers['title'] || title css_files = headers['css'].to_s.split(/,\s*/) js_files = headers['js'].to_s.split(/,\s*/) meta_data = Hash[*headers['meta'].to_s.scan(/(.*?)="(.*?)"(?:,\s*)?/).flatten] STDOUT << expand_tpl_file(header, binding) unless header.nil? STDOUT << open(filters, 'r+') { |io| io << body; io.close_write; wrap_in_article(expand_tpl(io.read, binding)) } STDOUT << expand_tpl_file(footer, binding) unless footer.nil?