mirror of
https://github.com/textmate/textmate.git
synced 2026-01-21 04:38:13 -05:00
This is when generating HTML for the release notes, manual, and, where we actually need this, list of contributions. Long-term we should probably switch to template tags as we are effectively adding code to the (otherwise declarative) build graph, which means we don’t have any way to tell if the generated HTML is up-to-date or not (as that would require analyzing the embedded ruby code).
106 lines
2.8 KiB
Ruby
Executable File
106 lines
2.8 KiB
Ruby
Executable File
#!/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
|
|
"<kbd class='tabTrigger'>#$1</kbd>"
|
|
elsif $2
|
|
"(<kbd class='keyEquivalent'>#$2</kbd>)"
|
|
else
|
|
"<kbd class='keyEquivalent'>#$&</kbd>"
|
|
end
|
|
end
|
|
end
|
|
|
|
def wrap_authors(src)
|
|
src.gsub(/ \*\[ (.+?) \]\* /x) do
|
|
"<span class='credit'>#$1</span>"
|
|
end
|
|
end
|
|
|
|
def wrap_in_article(html)
|
|
html.gsub(/<h2\b.*>.*<\/h2>(?m:.*?)(?=\s*<h2|\z)/) do
|
|
"<article>\n#$&\n</article>\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?
|