class Ronn::RoffFilter
Constants
- HTML_ROFF_ENTITIES
Public Class Methods
new(html, name, section, tagline, manual=nil, version=nil, date=nil)
click to toggle source
Convert Ronn
HTML to roff.
# File lib/ronn/roff.rb 9 def initialize(html, name, section, tagline, manual=nil, version=nil, date=nil) 10 @buf = [] 11 title_heading name, section, tagline, manual, version, date 12 doc = Hpricot(html) 13 remove_extraneous_elements! doc 14 normalize_whitespace! doc 15 block_filter doc 16 write "\n" 17 end
Public Instance Methods
to_s()
click to toggle source
# File lib/ronn/roff.rb 19 def to_s 20 @buf.join.gsub(/[ \t]+$/, '') 21 end
Protected Instance Methods
block_filter(node)
click to toggle source
# File lib/ronn/roff.rb 80 def block_filter(node) 81 if node.kind_of?(Array) || node.kind_of?(Hpricot::Elements) 82 node.each { |ch| block_filter(ch) } 83 84 elsif node.doc? 85 block_filter(node.children) 86 87 elsif node.text? 88 warn "unexpected text: %p", node 89 90 elsif node.elem? 91 case node.name 92 when 'div' 93 block_filter(node.children) 94 when 'h1' 95 # discard 96 when 'h2' 97 macro "SH", quote(escape(node.html)) 98 when 'h3' 99 macro "SS", quote(escape(node.html)) 100 101 when 'p' 102 prev = previous(node) 103 if prev && %w[dd li].include?(node.parent.name) 104 macro "IP" 105 elsif prev && !%w[h1 h2 h3].include?(prev.name) 106 macro "P" 107 end 108 inline_filter(node.children) 109 110 when 'pre' 111 prev = previous(node) 112 indent = prev.nil? || !%w[h1 h2 h3].include?(prev.name) 113 macro "IP", %w["" 4] if indent 114 macro "nf" 115 write "\n" 116 inline_filter(node.children) 117 macro "fi" 118 macro "IP", %w["" 0] if indent 119 120 when 'dl' 121 macro "TP" 122 block_filter(node.children) 123 when 'dt' 124 prev = previous(node) 125 macro "TP" unless prev.nil? 126 inline_filter(node.children) 127 write "\n" 128 when 'dd' 129 if node.at('p') 130 block_filter(node.children) 131 else 132 inline_filter(node.children) 133 end 134 write "\n" 135 136 when 'ol', 'ul' 137 block_filter(node.children) 138 macro "IP", %w["" 0] 139 when 'li' 140 case node.parent.name 141 when 'ol' 142 macro "IP", %W["#{node.position + 1}." 4] 143 when 'ul' 144 macro "IP", %w["\(bu" 4] 145 end 146 if node.at('p|ol|ul|dl|div') 147 block_filter(node.children) 148 else 149 inline_filter(node.children) 150 end 151 write "\n" 152 153 else 154 warn "unrecognized block tag: %p", node.name 155 end 156 157 else 158 fail "unexpected node: #{node.inspect}" 159 end 160 end
comment(text)
click to toggle source
# File lib/ronn/roff.rb 276 def comment(text) 277 writeln %[.\\" #{text}] 278 end
escape(text)
click to toggle source
# File lib/ronn/roff.rb 241 def escape(text) 242 return text.to_s if text.nil? || text.empty? 243 ent = HTML_ROFF_ENTITIES 244 text = text.dup 245 text.gsub!(/&#x([0-9A-Fa-f]+);/) { $1.to_i(16).chr } # hex entities 246 text.gsub!(/&#(\d+);/) { $1.to_i.chr } # dec entities 247 text.gsub!('\\', '\e') # backslash 248 text.gsub!(/['.-]/) { |m| "\\#{m}" } # control chars 249 text.gsub!(/(&[A-Za-z]+;)/) { ent[$1] || $1 } # named entities 250 text.gsub!('&', '&') # amps 251 text 252 end
inline_filter(node)
click to toggle source
# File lib/ronn/roff.rb 162 def inline_filter(node) 163 return unless node # is an empty node 164 165 if node.kind_of?(Array) || node.kind_of?(Hpricot::Elements) 166 node.each { |ch| inline_filter(ch) } 167 168 elsif node.text? 169 text = node.to_html.dup 170 write escape(text) 171 172 elsif node.elem? 173 case node.name 174 when 'span' 175 inline_filter(node.children) 176 when 'code' 177 if child_of?(node, 'pre') 178 inline_filter(node.children) 179 else 180 write '\fB' 181 inline_filter(node.children) 182 write '\fR' 183 end 184 185 when 'b', 'strong', 'kbd', 'samp' 186 write '\fB' 187 inline_filter(node.children) 188 write '\fR' 189 190 when 'var', 'em', 'i', 'u' 191 write '\fI' 192 inline_filter(node.children) 193 write '\fR' 194 195 when 'br' 196 macro 'br' 197 198 when 'a' 199 if node.classes.include?('man-ref') 200 inline_filter(node.children) 201 elsif node.has_attribute?('data-bare-link') 202 write '\fI' 203 inline_filter(node.children) 204 write '\fR' 205 else 206 inline_filter(node.children) 207 write ' ' 208 write '\fI' 209 write escape(node.attributes['href']) 210 write '\fR' 211 end 212 else 213 warn "unrecognized inline tag: %p", node.name 214 end 215 216 else 217 fail "unexpected node: #{node.inspect}" 218 end 219 end
macro(name, value=nil)
click to toggle source
# File lib/ronn/roff.rb 221 def macro(name, value=nil) 222 writeln ".\n.#{[name, value].compact.join(' ')}" 223 end
normalize_whitespace!(node)
click to toggle source
# File lib/ronn/roff.rb 47 def normalize_whitespace!(node) 48 case 49 when node.kind_of?(Array) || node.kind_of?(Hpricot::Elements) 50 node.to_a.dup.each { |ch| normalize_whitespace! ch } 51 when node.text? 52 preceding, following = node.previous, node.next 53 content = node.content.gsub(/[\n ]+/m, ' ') 54 if preceding.nil? || block_element?(preceding.name) || 55 preceding.name == 'br' 56 content.lstrip! 57 end 58 if following.nil? || block_element?(following.name) || 59 following.name == 'br' 60 content.rstrip! 61 end 62 if content.empty? 63 node.parent.children.delete(node) 64 else 65 node.content = content 66 end 67 when node.elem? && node.name == 'pre' 68 # stop traversing 69 when node.elem? && node.children 70 normalize_whitespace! node.children 71 when node.elem? 72 # element has no children 73 when node.doc? 74 normalize_whitespace! node.children 75 else 76 warn "unexpected node during whitespace normalization: %p", node 77 end 78 end
previous(node)
click to toggle source
# File lib/ronn/roff.rb 24 def previous(node) 25 if node.respond_to?(:previous) 26 prev = node.previous 27 prev = prev.previous until prev.nil? || prev.elem? 28 prev 29 end 30 end
quote(text)
click to toggle source
# File lib/ronn/roff.rb 254 def quote(text) 255 "\"#{text.gsub(/"/, '\\"')}\"" 256 end
remove_extraneous_elements!(doc)
click to toggle source
# File lib/ronn/roff.rb 39 def remove_extraneous_elements!(doc) 40 doc.traverse_all_element do |node| 41 if node.comment? || node.procins? || node.doctype? || node.xmldecl? 42 node.parent.children.delete(node) 43 end 44 end 45 end
title_heading(name, section, tagline, manual, version, date)
click to toggle source
# File lib/ronn/roff.rb 32 def title_heading(name, section, tagline, manual, version, date) 33 comment "generated with Ronn/v#{Ronn.version}" 34 comment "http://github.com/rtomayko/ronn/tree/#{Ronn.revision}" 35 return if name.nil? 36 macro "TH", %["#{escape(name.upcase)}" "#{section}" "#{date.strftime('%B %Y')}" "#{version}" "#{manual}"] 37 end
warn(text, *args)
click to toggle source
# File lib/ronn/roff.rb 280 def warn(text, *args) 281 $stderr.puts "warn: #{text}" % args 282 end
write(text)
click to toggle source
write text to output buffer
# File lib/ronn/roff.rb 259 def write(text) 260 return if text.nil? || text.empty? 261 # lines cannot start with a '.'. insert zero-width character before. 262 if text[0,2] == '\.' && 263 (@buf.last && @buf.last[-1] == ?\n) 264 @buf << '\&' 265 end 266 @buf << text 267 end
writeln(text)
click to toggle source
write text to output buffer on a new line.
# File lib/ronn/roff.rb 270 def writeln(text) 271 write "\n" if @buf.last && @buf.last[-1] != ?\n 272 write text 273 write "\n" 274 end