Created
August 19, 2011 13:26
-
-
Save drKreso/1156784 to your computer and use it in GitHub Desktop.
Terminal.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rexml/parsers/baseparser' | |
module Kramdown | |
module Converter | |
# Converts a Kramdown::Document to Terminal | |
class Terminal < Html | |
def convert_blank(el, indent) | |
" " | |
end | |
def convert_text(el, indent) | |
escape_html(el.value, :text) | |
end | |
def convert_p(el, indent) | |
if el.options[:transparent] | |
inner(el, indent) | |
else | |
"#{' '*indent}<pilence#{html_attributes(el.attr)}>#{inner(el, indent)}</p>\n" | |
end | |
end | |
def convert_codeblock(el, indent) | |
if el.attr['lang'] && HIGHLIGHTING_AVAILABLE | |
attr = el.attr.dup | |
opts = {:wrap => @options[:coderay_wrap], :line_numbers => @options[:coderay_line_numbers], | |
:line_number_start => @options[:coderay_line_number_start], :tab_width => @options[:coderay_tab_width], | |
:bold_every => @options[:coderay_bold_every], :css => @options[:coderay_css]} | |
result = CodeRay.scan(el.value, attr.delete('lang').to_sym).html(opts).chomp << "\n" | |
"#{' '*indent}<div#{html_attributes(attr)}>#{result}#{' '*indent}</div>\n" | |
else | |
result = escape_html(el.value) | |
result.chomp! | |
if el.attr['class'].to_s =~ /\bshow-whitespaces\b/ | |
result.gsub!(/(?:(^[ \t]+)|([ \t]+$)|([ \t]+))/) do |m| | |
suffix = ($1 ? '-l' : ($2 ? '-r' : '')) | |
m.scan(/./).map do |c| | |
case c | |
when "\t" then "<span class=\"ws-tab#{suffix}\">\t</span>" | |
when " " then "<span class=\"ws-space#{suffix}\">⋅</span>" | |
end | |
end.join('') | |
end | |
end | |
"#{' '*indent}<pre#{html_attributes(el.attr)}><code>#{result}\n</code></pre>\n" | |
end | |
end | |
def convert_blockquote(el, indent) | |
"#{' '*indent}<blockquote#{html_attributes(el.attr)}>\n#{inner(el, indent)}#{' '*indent}</blockquote>\n" | |
end | |
def convert_header(el, indent) | |
attr = el.attr.dup | |
if @options[:auto_ids] && !attr['id'] | |
attr['id'] = generate_id(el.options[:raw_text]) | |
end | |
@toc << [el.options[:level], attr['id'], el.children] if attr['id'] && in_toc?(el) | |
"#{' '*indent}<h#{el.options[:level]}#{html_attributes(attr)}>#{inner(el, indent)}</h#{el.options[:level]}>\n" | |
end | |
def convert_hr(el, indent) | |
"#{' '*indent}<hr />\n" | |
end | |
def convert_ul(el, indent) | |
if !@toc_code && (el.options[:ial][:refs].include?('toc') rescue nil) && (el.type == :ul || el.type == :ol) | |
@toc_code = [el.type, el.attr, (0..128).to_a.map{|a| rand(36).to_s(36)}.join] | |
@toc_code.last | |
else | |
"#{' '*indent}<#{el.type}#{html_attributes(el.attr)}>\n#{inner(el, indent)}#{' '*indent}</#{el.type}>\n" | |
end | |
end | |
alias :convert_ol :convert_ul | |
alias :convert_dl :convert_ul | |
def convert_li(el, indent) | |
output = ' '*indent << "<#{el.type}" << html_attributes(el.attr) << ">" | |
res = inner(el, indent) | |
if el.children.empty? || (el.children.first.type == :p && el.children.first.options[:transparent]) | |
output << res << (res =~ /\n\Z/ ? ' '*indent : '') | |
else | |
output << "\n" << res << ' '*indent | |
end | |
output << "</#{el.type}>\n" | |
end | |
alias :convert_dd :convert_li | |
def convert_dt(el, indent) | |
"#{' '*indent}<dt#{html_attributes(el.attr)}>#{inner(el, indent)}</dt>\n" | |
end | |
# A list of all HTML tags that need to have a body (even if the body is empty). | |
HTML_TAGS_WITH_BODY=['div', 'script', 'iframe', 'textarea', 'a'] # :nodoc: | |
def convert_html_element(el, indent) | |
res = inner(el, indent) | |
if el.options[:category] == :span | |
"<#{el.value}#{html_attributes(el.attr)}" << (!res.empty? || HTML_TAGS_WITH_BODY.include?(el.value) ? ">#{res}</#{el.value}>" : " />") | |
else | |
output = '' | |
output << ' '*indent if @stack.last.type != :html_element || @stack.last.options[:content_model] != :raw | |
output << "<#{el.value}#{html_attributes(el.attr)}" | |
if !res.empty? && el.options[:content_model] != :block | |
output << ">#{res}</#{el.value}>" | |
elsif !res.empty? | |
output << ">\n#{res.chomp}\n" << ' '*indent << "</#{el.value}>" | |
elsif HTML_TAGS_WITH_BODY.include?(el.value) | |
output << "></#{el.value}>" | |
else | |
output << " />" | |
end | |
output << "\n" if @stack.last.type != :html_element || @stack.last.options[:content_model] != :raw | |
output | |
end | |
end | |
def convert_xml_comment(el, indent) | |
if el.options[:category] == :block && (@stack.last.type != :html_element || @stack.last.options[:content_model] != :raw) | |
' '*indent << el.value << "\n" | |
else | |
el.value | |
end | |
end | |
alias :convert_xml_pi :convert_xml_comment | |
def convert_table(el, indent) | |
"#{' '*indent}<table#{html_attributes(el.attr)}>\n#{inner(el, indent)}#{' '*indent}</table>\n" | |
end | |
def convert_thead(el, indent) | |
"#{' '*indent}<#{el.type}#{html_attributes(el.attr)}>\n#{inner(el, indent)}#{' '*indent}</#{el.type}>\n" | |
end | |
alias :convert_tbody :convert_thead | |
alias :convert_tfoot :convert_thead | |
alias :convert_tr :convert_thead | |
ENTITY_NBSP = ::Kramdown::Utils::Entities.entity('nbsp') # :nodoc: | |
def convert_td(el, indent) | |
res = inner(el, indent) | |
type = (@stack[-2].type == :thead ? :th : :td) | |
attr = el.attr | |
alignment = @stack[-3].options[:alignment][@stack.last.children.index(el)] | |
if alignment != :default | |
attr = el.attr.dup | |
attr['style'] = (attr.has_key?('style') ? "#{attr['style']}; ": '') << "text-align: #{alignment}" | |
end | |
"#{' '*indent}<#{type}#{html_attributes(attr)}>#{res.empty? ? entity_to_str(ENTITY_NBSP) : res}</#{type}>\n" | |
end | |
def convert_comment(el, indent) | |
if el.options[:category] == :block | |
"#{' '*indent}<!-- #{el.value} -->\n" | |
else | |
"<!-- #{el.value} -->" | |
end | |
end | |
def convert_br(el, indent) | |
"<br />" | |
end | |
def convert_a(el, indent) | |
res = inner(el, indent) | |
attr = el.attr.dup | |
if attr['href'] =~ /^mailto:/ | |
attr['href'] = obfuscate('mailto') << ":" << obfuscate(attr['href'].sub(/^mailto:/, '')) | |
res = obfuscate(res) | |
end | |
"<a#{html_attributes(attr)}>#{res}</a>" | |
end | |
def convert_img(el, indent) | |
"<img#{html_attributes(el.attr)} />" | |
end | |
def convert_codespan(el, indent) | |
if el.attr['lang'] && HIGHLIGHTING_AVAILABLE | |
attr = el.attr.dup | |
result = CodeRay.scan(el.value, attr.delete('lang').to_sym).html(:wrap => :span, :css => @options[:coderay_css]).chomp | |
"<code#{html_attributes(attr)}>#{result}</code>" | |
else | |
"<code#{html_attributes(el.attr)}>#{escape_html(el.value)}</code>" | |
end | |
end | |
def convert_footnote(el, indent) | |
number = @footnote_counter | |
@footnote_counter += 1 | |
@footnotes << [el.options[:name], el.value] | |
"<sup id=\"fnref:#{el.options[:name]}\"><a href=\"#fn:#{el.options[:name]}\" rel=\"footnote\">#{number}</a></sup>" | |
end | |
def convert_raw(el, indent) | |
if !el.options[:type] || el.options[:type].empty? || el.options[:type].include?('html') | |
el.value + (el.options[:category] == :block ? "\n" : '') | |
else | |
'' | |
end | |
end | |
def convert_em(el, indent) | |
"<#{el.type}#{html_attributes(el.attr)}>#{inner(el, indent)}</#{el.type}>" | |
end | |
alias :convert_strong :convert_em | |
def convert_entity(el, indent) | |
entity_to_str(el.value, el.options[:original]) | |
end | |
TYPOGRAPHIC_SYMS = { | |
:mdash => [::Kramdown::Utils::Entities.entity('mdash')], | |
:ndash => [::Kramdown::Utils::Entities.entity('ndash')], | |
:hellip => [::Kramdown::Utils::Entities.entity('hellip')], | |
:laquo_space => [::Kramdown::Utils::Entities.entity('laquo'), ::Kramdown::Utils::Entities.entity('nbsp')], | |
:raquo_space => [::Kramdown::Utils::Entities.entity('nbsp'), ::Kramdown::Utils::Entities.entity('raquo')], | |
:laquo => [::Kramdown::Utils::Entities.entity('laquo')], | |
:raquo => [::Kramdown::Utils::Entities.entity('raquo')] | |
} # :nodoc: | |
def convert_typographic_sym(el, indent) | |
TYPOGRAPHIC_SYMS[el.value].map {|e| entity_to_str(e)}.join('') | |
end | |
def convert_smart_quote(el, indent) | |
entity_to_str(smart_quote_entity(el)) | |
end | |
def convert_math(el, indent) | |
block = (el.options[:category] == :block) | |
"<script type=\"math/tex#{block ? '; mode=display' : ''}\">#{el.value}</script>#{block ? "\n" : ''}" | |
end | |
def convert_abbreviation(el, indent) | |
title = @root.options[:abbrev_defs][el.value] | |
"<abbr#{!title.empty? ? " title=\"#{title}\"" : ''}>#{el.value}</abbr>" | |
end | |
def convert_root(el, indent) | |
result = inner(el, indent) | |
result << footnote_content | |
if @toc_code | |
toc_tree = generate_toc_tree(@toc, @toc_code[0], @toc_code[1] || {}) | |
text = if toc_tree.children.size > 0 | |
convert(toc_tree, 0) | |
else | |
'' | |
end | |
result.sub!(/#{@toc_code.last}/, text) | |
end | |
result | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment