Class: Kramdown::Converter::Rfc2629
- Includes:
- Utils::Html
- Defined in:
- lib/kramdown-rfc2629.rb
Overview
Converts a Kramdown::Document to HTML.
Constant Summary collapse
- INDENTATION =
Defines the amount of indentation used when nesting XML tags.
2- STYLES =
{ul: 'symbols', ol: 'numbers', dl: 'hanging'}
- HTML_TAGS_WITH_BODY =
['div', 'script']
- ALIGNMENTS =
{ default: :left, left: :left, right: :right, center: :center}
- COLS_ALIGN =
{ "l" => :left, "c" => :center, "r" => :right}
- REFCACHEDIR =
".refcache"- XML_RESOURCE_ORG_MAP =
{ "RFC" => "bibxml", "I-D" => "bibxml3", "W3C" => "bibxml4", "3GPP" => "bibxml5", "ANSI" => "bibxml2", "CCITT" => "bibxml2", "FIPS" => "bibxml2", "IANA" => "bibxml2", "IEEE" => "bibxml2", "ISO" => "bibxml2", "ITU" => "bibxml2", "NIST" => "bibxml2", "OASIS" => "bibxml2", "PKCS" => "bibxml2", }
- XML_RESOURCE_ORG_HOST =
XML_RESOURCE_ORG_HOST = ENV || “xml.resource.org”
ENV["XML_RESOURCE_ORG_HOST"] || "xml2rfc.tools.ietf.org"
- XML_RESOURCE_ORG_PREFIX =
ENV["XML_RESOURCE_ORG_PREFIX"] || "http://#{XML_RESOURCE_ORG_HOST}/public/rfc"
- EMPH =
{ em: "emph", strong: "strong"}
- 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')] }
Instance Method Summary collapse
- #convert(el, indent = -INDENTATION,, opts = {}) ⇒ Object
- #convert1(el, indent, opts = {}) ⇒ Object
- #convert_a(el, indent, opts) ⇒ Object
-
#convert_abbreviation(el, indent, opts) ⇒ Object
XXX: This is wrong.
- #convert_blank(el, indent, opts) ⇒ Object
- #convert_blockquote(el, indent, opts) ⇒ Object
- #convert_br(el, indent, opts) ⇒ Object
- #convert_codeblock(el, indent, opts) ⇒ Object
- #convert_codespan(el, indent, opts) ⇒ Object
- #convert_comment(el, indent, opts) ⇒ Object
- #convert_dd(el, indent, opts) ⇒ Object
-
#convert_dt(el, indent, opts) ⇒ Object
SERIOUSLY BAD HACK:.
- #convert_em(el, indent, opts) ⇒ Object (also: #convert_strong)
- #convert_entity(el, indent, opts) ⇒ Object
-
#convert_footnote(el, indent, opts) ⇒ Object
XXX: This is wrong.
- #convert_header(el, indent, opts) ⇒ Object
-
#convert_hr(el, indent, opts) ⇒ Object
misuse for page break.
- #convert_html_element(el, indent, opts) ⇒ Object
-
#convert_img(el, indent, opts) ⇒ Object
misuse the tag!.
- #convert_li(el, indent, opts) ⇒ Object
-
#convert_math(el, indent, opts) ⇒ Object
XXX: This is wrong.
- #convert_p(el, indent, opts) ⇒ Object
- #convert_raw(el, indent, opts) ⇒ Object
- #convert_root(el, indent, opts) ⇒ Object
- #convert_smart_quote(el, indent, opts) ⇒ Object
-
#convert_table(el, indent, opts) ⇒ Object
This only works for tables with headers.
- #convert_td(el, indent, opts) ⇒ Object (also: #convert_th)
- #convert_text(el, indent, opts) ⇒ Object
- #convert_thead(el, indent, opts) ⇒ Object (also: #convert_tbody, #convert_tfoot, #convert_tr)
- #convert_typographic_sym(el, indent, opts) ⇒ Object
- #convert_ul(el, indent, opts) ⇒ Object (also: #convert_ol, #convert_dl)
- #convert_xml_comment(el, indent, opts) ⇒ Object (also: #convert_xml_pi, #convert_html_doctype)
- #convert_xref(el, indent, opts) ⇒ Object
- #el_html_attributes(el) ⇒ Object
- #el_html_attributes_with(el, defattr) ⇒ Object
- #end_sections(to_level, indent) ⇒ Object
- #get_and_cache_resource(url, tn = Time.now, tvalid = 7200) ⇒ Object
-
#initialize(*doc) ⇒ Rfc2629
constructor
Initialize the XML converter with the given Kramdown document
doc. - #inner(el, indent, opts) ⇒ Object
- #inner_a(el, indent, opts) ⇒ Object
-
#obfuscate(text) ⇒ Object
Helper method for obfuscating the
textby using XML entities. - #saner_generate_id(value) ⇒ Object
Constructor Details
#initialize(*doc) ⇒ Rfc2629
Initialize the XML converter with the given Kramdown document doc.
88 89 90 91 92 |
# File 'lib/kramdown-rfc2629.rb', line 88 def initialize(*doc) super @sec_level = 1 @in_dt = 0 end |
Instance Method Details
#convert(el, indent = -INDENTATION,, opts = {}) ⇒ Object
94 95 96 97 98 99 |
# File 'lib/kramdown-rfc2629.rb', line 94 def convert(el, indent = -INDENTATION, opts = {}) if el.children[-1].type == :raw raw = convert1(el.children.pop, indent, opts) end "#{convert1(el, indent, opts)}#{end_sections(1, indent)}#{raw}" end |
#convert1(el, indent, opts = {}) ⇒ Object
101 102 103 104 |
# File 'lib/kramdown-rfc2629.rb', line 101 def convert1(el, indent, opts = {}) el.rfc2629_fix send("convert_#{el.type}", el, indent, opts) end |
#convert_a(el, indent, opts) ⇒ Object
334 335 336 337 338 339 340 341 342 343 344 345 |
# File 'lib/kramdown-rfc2629.rb', line 334 def convert_a(el, indent, opts) do_obfuscation = el.attr['href'] =~ /^mailto:/ if do_obfuscation el = el.deep_clone href = obfuscate(el.attr['href'].sub(/^mailto:/, '')) mailto = obfuscate('mailto') el.attr['href'] = "#{mailto}:#{href}" end res = inner(el, indent, opts) res = obfuscate(res) if do_obfuscation "<eref#{el_html_attributes(el)}>#{res}</eref>" end |
#convert_abbreviation(el, indent, opts) ⇒ Object
XXX: This is wrong
468 469 470 471 472 |
# File 'lib/kramdown-rfc2629.rb', line 468 def convert_abbreviation(el, indent, opts) # XXX: This is wrong title = @doc.parse_infos[:abbrev_defs][el.value] title = nil if title.empty? "<abbr#{title ? " title=\"#{title}\"" : ''}>#{el.value}</abbr>" end |
#convert_blank(el, indent, opts) ⇒ Object
118 119 120 |
# File 'lib/kramdown-rfc2629.rb', line 118 def convert_blank(el, indent, opts) "\n" end |
#convert_blockquote(el, indent, opts) ⇒ Object
170 171 172 |
# File 'lib/kramdown-rfc2629.rb', line 170 def convert_blockquote(el, indent, opts) "#{' '*indent}<t><list style='empty'#{el_html_attributes(el)}>\n#{inner(el, indent, opts)}#{' '*indent}</list></t>\n" end |
#convert_br(el, indent, opts) ⇒ Object
330 331 332 |
# File 'lib/kramdown-rfc2629.rb', line 330 def convert_br(el, indent, opts) "<vspace />" end |
#convert_codeblock(el, indent, opts) ⇒ Object
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 |
# File 'lib/kramdown-rfc2629.rb', line 138 def convert_codeblock(el, indent, opts) # el.attr['anchor'] ||= saner_generate_id(el.value) -- no longer in 1.0.6 result = el.value blockclass = el.attr.delete('class') if blockclass == 'language-tbreak' result = result.lines.map {|line| [line.chomp, 0]} spaceind = 0 result.each_with_index {|pair, index| if pair[0] == '' result[spaceind][1] += 1 pair[0] = nil unless index == spaceind else spaceind = index end } # $stderr.puts(result.inspect) result = result.map {|line, space| "<![CDATA[#{line.gsub(/^\s+/) {|s| "\u00A0" * s.size}}]]><vspace blankLines=\"#{space}\"/>" if line }.compact.join("\n") "#{' '*indent}<t>#{result}</t>\n" else if blockclass $stderr.puts "*** Unimplemented block class: #{blockclass}" end # compensate for XML2RFC idiosyncracy by insisting on a blank line unless el.attr.delete('tight') result[0,0] = "\n" unless result[0,1] == "\n" end "#{' '*indent}<figure#{el_html_attributes(el)}><artwork><![CDATA[#{result}#{result =~ /\n\Z/ ? '' : "\n"}]]></artwork></figure>\n" end end |
#convert_codespan(el, indent, opts) ⇒ Object
416 417 418 419 |
# File 'lib/kramdown-rfc2629.rb', line 416 def convert_codespan(el, indent, opts) attrstring = el_html_attributes_with(el, {"style" => 'verb'}) "<spanx#{attrstring}>#{escape_html(el.value)}</spanx>" end |
#convert_comment(el, indent, opts) ⇒ Object
321 322 323 324 325 326 327 328 |
# File 'lib/kramdown-rfc2629.rb', line 321 def convert_comment(el, indent, opts) ## Don't actually output all those comments into the XML: # if el.options[:category] == :block # "#{' '*indent}<!-- #{el.value} -->\n" # else # "<!-- #{el.value} -->" # end end |
#convert_dd(el, indent, opts) ⇒ Object
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/kramdown-rfc2629.rb', line 229 def convert_dd(el, indent, opts) output = ' '*indent if @in_dt == 1 @in_dt = 0 else output << "<t#{el_html_attributes(el)}>" end res = inner(el, indent+INDENTATION, opts.merge(unpacked: true)) # if el.children.empty? || el.children.first.options[:category] != :block output << res << (res =~ /\n\Z/ ? ' '*indent : '') # else FIXME: The latter case is needed for more complex cases # output << "\n" << res << ' '*indent # end output << "</t>\n" end |
#convert_dt(el, indent, opts) ⇒ Object
SERIOUSLY BAD HACK:
245 246 247 248 249 250 251 |
# File 'lib/kramdown-rfc2629.rb', line 245 def convert_dt(el, indent, opts) # SERIOUSLY BAD HACK: close = "#{' '*indent}</t>\n" * @in_dt @in_dt = 1 vspace = opts[:vspace] vspaceel = "<vspace blankLines='#{vspace}'/>" if vspace "#{close}#{' '*indent}<t#{el_html_attributes(el)} hangText='#{inner(el, indent, opts)}'>#{vspaceel}\n" end |
#convert_em(el, indent, opts) ⇒ Object Also known as: convert_strong
432 433 434 435 |
# File 'lib/kramdown-rfc2629.rb', line 432 def convert_em(el, indent, opts) attrstring = el_html_attributes_with(el, {"style" => EMPH[el.type]}) "<spanx#{attrstring}>#{inner(el, indent, opts)}</spanx>" end |
#convert_entity(el, indent, opts) ⇒ Object
438 439 440 |
# File 'lib/kramdown-rfc2629.rb', line 438 def convert_entity(el, indent, opts) entity_to_str(el.value) end |
#convert_footnote(el, indent, opts) ⇒ Object
XXX: This is wrong.
421 422 423 |
# File 'lib/kramdown-rfc2629.rb', line 421 def convert_footnote(el, indent, opts) # XXX: This is wrong. "<xref target='#{escape_html(el.value)}'#{el_html_attributes(el)}/>" end |
#convert_header(el, indent, opts) ⇒ Object
187 188 189 190 191 192 193 194 195 196 |
# File 'lib/kramdown-rfc2629.rb', line 187 def convert_header(el, indent, opts) # todo: handle appendix tags el = el.deep_clone = @doc ? @doc. : @options # XXX: 0.11 vs. 0.12 if [:auto_ids] && !el.attr['anchor'] el.attr['anchor'] = saner_generate_id(el.[:raw_text]) end el.attr['title'] = inner(el, indent, opts) "#{end_sections(el.[:level], indent)}#{' '*indent}<section#{@sec_level += 1; el_html_attributes(el)}>\n" end |
#convert_hr(el, indent, opts) ⇒ Object
misuse for page break
198 199 200 |
# File 'lib/kramdown-rfc2629.rb', line 198 def convert_hr(el, indent, opts) # misuse for page break "#{' '*indent}<t><vspace blankLines='999' /></t>\n" end |
#convert_html_element(el, indent, opts) ⇒ Object
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'lib/kramdown-rfc2629.rb', line 255 def convert_html_element(el, indent, opts) res = inner(el, indent, opts) if el.[:category] == :span "<#{el.value}#{el_html_attributes(el)}" << (!res.empty? ? ">#{res}</#{el.value}>" : " />") else output = '' output << ' '*indent if !el.[:parent_is_raw] output << "<#{el.value}#{el_html_attributes(el)}" if !res.empty? && el.[:parse_type] != :block output << ">#{res}</#{el.value}>" elsif !res.empty? output << ">\n#{res}" << ' '*indent << "</#{el.value}>" elsif HTML_TAGS_WITH_BODY.include?(el.value) output << "></#{el.value}>" else output << " />" end output << "\n" if el.[:outer_element] || !el.[:parent_is_raw] output end end |
#convert_img(el, indent, opts) ⇒ Object
misuse the tag!
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 |
# File 'lib/kramdown-rfc2629.rb', line 392 def convert_img(el, indent, opts) # misuse the tag! if a = el.attr alt = a.delete('alt').strip alt = '' if alt == '!' # work around re-wrap uglyness if anchor = a.delete('src') a['target'] = anchor end end if alt == ":include:" # Really bad misuse of tag... to_insert = "" anchor.scan(/(W3C|3GPP|[A-Z-]+)[.]?([A-Za-z0-9.-]+)/) do |t, n| fn = "reference.#{t}.#{n}.xml" sub = XML_RESOURCE_ORG_MAP[t] puts "Huh: ${fn}" unless sub url = "#{XML_RESOURCE_ORG_PREFIX}/#{sub}/#{fn}" to_insert = get_and_cache_resource(url) end to_insert.gsub(/<\?xml version=["']1.0["'] encoding=["']UTF-8["']\?>/, ''). gsub(/(anchor=["'])([0-9])/) { "#{$1}_#{$2}"} # can't start an ID with a number else "<xref#{el_html_attributes(el)}>#{alt}</xref>" end end |
#convert_li(el, indent, opts) ⇒ Object
216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/kramdown-rfc2629.rb', line 216 def convert_li(el, indent, opts) res_a = inner_a(el, indent, opts) if el.children.empty? || el.children.first.[:category] == :span res = res_a.join('') else # merge multiple <t> elements res = res_a.select { |x| x.strip != '' }.map { |x| x.sub(/\A\s*<t>(.*)<\/t>\s*\Z/m) { $1} }.join("#{' '*indent}<vspace blankLines='1'/>\n").gsub(%r{(</list>)\s*<vspace blankLines='1'/>}) { $1 }.gsub(%r{<vspace blankLines='1'/>\s*(<list)}) { $1 } end "#{' '*indent}<t#{el_html_attributes(el)}>#{res}#{(res =~ /\n\Z/ ? ' '*indent : '')}</t>\n" end |
#convert_math(el, indent, opts) ⇒ Object
XXX: This is wrong
459 460 461 462 463 464 465 466 |
# File 'lib/kramdown-rfc2629.rb', line 459 def convert_math(el, indent, opts) # XXX: This is wrong el = el.deep_clone el.attr['class'] ||= '' el.attr['class'] += (el.attr['class'].empty? ? '' : ' ') + 'math' type = 'span' type = 'div' if el.[:category] == :block "<#{type}#{el_html_attributes(el)}>#{escape_html(el.value, :text)}</#{type}>#{type == 'div' ? "\n" : ''}" end |
#convert_p(el, indent, opts) ⇒ Object
126 127 128 129 130 131 132 |
# File 'lib/kramdown-rfc2629.rb', line 126 def convert_p(el, indent, opts) if (el.children.size == 1 && el.children[0].type == :img) || opts[:unpacked] inner(el, indent, opts) # Part of the bad reference hack else "#{' '*indent}<t#{el_html_attributes(el)}>#{inner(el, indent, opts)}</t>\n" end end |
#convert_raw(el, indent, opts) ⇒ Object
425 426 427 428 |
# File 'lib/kramdown-rfc2629.rb', line 425 def convert_raw(el, indent, opts) end_sections(1, indent) + el.value + (el.[:category] == :block ? "\n" : '') end |
#convert_root(el, indent, opts) ⇒ Object
474 475 476 |
# File 'lib/kramdown-rfc2629.rb', line 474 def convert_root(el, indent, opts) result = inner(el, indent, opts) end |
#convert_smart_quote(el, indent, opts) ⇒ Object
455 456 457 |
# File 'lib/kramdown-rfc2629.rb', line 455 def convert_smart_quote(el, indent, opts) entity_to_str(::Kramdown::Utils::Entities.entity(el.value.to_s)) end |
#convert_table(el, indent, opts) ⇒ Object
This only works for tables with headers
290 291 292 293 294 |
# File 'lib/kramdown-rfc2629.rb', line 290 def convert_table(el, indent, opts) # This only works for tables with headers alignment = el.[:alignment].map { |al| ALIGNMENTS[al]} cols = (el.attr.delete("cols") || "").split(' ') "#{' '*indent}<texttable#{el_html_attributes(el)}>\n#{inner(el, indent, opts.merge(table_alignment: alignment, table_cols: cols))}#{' '*indent}</texttable>\n" end |
#convert_td(el, indent, opts) ⇒ Object Also known as: convert_th
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
# File 'lib/kramdown-rfc2629.rb', line 303 def convert_td(el, indent, opts) if alignment = opts[:table_alignment] alignment = alignment.shift if cols = opts[:table_cols].shift md = cols.match(/(\d*)(.*)/) widthopt = "width='#{md[1]}' " if md[1].to_i != 0 alignment = COLS_ALIGN[md[2]] || :left end end res = inner(el, indent, opts) if alignment "#{' '*indent}<ttcol #{widthopt}align='#{alignment}'#{el_html_attributes(el)}>#{res.empty? ? " " : res}</ttcol>\n" else "#{' '*indent}<c#{el_html_attributes(el)}>#{res.empty? ? " " : res}</c>\n" end end |
#convert_text(el, indent, opts) ⇒ Object
122 123 124 |
# File 'lib/kramdown-rfc2629.rb', line 122 def convert_text(el, indent, opts) escape_html(el.value, :text) end |
#convert_thead(el, indent, opts) ⇒ Object Also known as: convert_tbody, convert_tfoot, convert_tr
296 297 298 |
# File 'lib/kramdown-rfc2629.rb', line 296 def convert_thead(el, indent, opts) inner(el, indent, opts) end |
#convert_typographic_sym(el, indent, opts) ⇒ Object
451 452 453 |
# File 'lib/kramdown-rfc2629.rb', line 451 def convert_typographic_sym(el, indent, opts) TYPOGRAPHIC_SYMS[el.value].map {|e| entity_to_str(e)}.join('') end |
#convert_ul(el, indent, opts) ⇒ Object Also known as: convert_ol, convert_dl
204 205 206 207 208 209 210 211 212 |
# File 'lib/kramdown-rfc2629.rb', line 204 def convert_ul(el, indent, opts) opts = opts.merge(vspace: el.attr.delete('vspace')) attrstring = el_html_attributes_with(el, {"style" => STYLES[el.type]}) if opts[:unpacked] "#{' '*indent}<list#{attrstring}>\n#{inner(el, indent, opts)}#{' '*indent}</list>\n" else "#{' '*indent}<t><list#{attrstring}>\n#{inner(el, indent, opts)}#{' '*indent}</list></t>\n" end end |
#convert_xml_comment(el, indent, opts) ⇒ Object Also known as: convert_xml_pi, convert_html_doctype
277 278 279 280 281 282 283 |
# File 'lib/kramdown-rfc2629.rb', line 277 def convert_xml_comment(el, indent, opts) if el.[:category] == :block && !el.[:parent_is_raw] ' '*indent + el.value + "\n" else el.value end end |
#convert_xref(el, indent, opts) ⇒ Object
347 348 349 350 351 352 353 354 |
# File 'lib/kramdown-rfc2629.rb', line 347 def convert_xref(el, indent, opts) target = el.attr['target'] if target[0] == "&" "#{target};" else "<xref#{el_html_attributes(el)}/>" end end |
#el_html_attributes(el) ⇒ Object
75 76 77 |
# File 'lib/kramdown-rfc2629.rb', line 75 def el_html_attributes(el) html_attributes(el.attr) end |
#el_html_attributes_with(el, defattr) ⇒ Object
78 79 80 |
# File 'lib/kramdown-rfc2629.rb', line 78 def el_html_attributes_with(el, defattr) html_attributes(defattr.merge(el.attr)) end |
#end_sections(to_level, indent) ⇒ Object
174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/kramdown-rfc2629.rb', line 174 def end_sections(to_level, indent) if indent < 0 indent = 0 end if @sec_level >= to_level delta = (@sec_level - to_level) @sec_level = to_level "#{' '*indent}</section>\n" * delta else $stderr.puts "Incorrect section nesting: Need to start with 1" end end |
#get_and_cache_resource(url, tn = Time.now, tvalid = 7200) ⇒ Object
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 |
# File 'lib/kramdown-rfc2629.rb', line 357 def get_and_cache_resource(url, tn = Time.now, tvalid = 7200) Dir.mkdir(REFCACHEDIR) unless Dir.exists?(REFCACHEDIR) fn = "#{REFCACHEDIR}/#{File.basename(url)}" f = File.stat(fn) rescue nil if !f || tn - f.ctime >= tvalid $stderr.puts "#{fn}: #{f && tn-f.ctime}" `cd #{REFCACHEDIR}; wget -t 3 -T 20 -Nnv "#{url}"` # ignore errors if offline (hack) begin File.utime nil, nil, fn rescue Errno::ENOENT warn "Can't fetch #{url} -- is wget in path?" end end File.read(fn) end |
#inner(el, indent, opts) ⇒ Object
114 115 116 |
# File 'lib/kramdown-rfc2629.rb', line 114 def inner(el, indent, opts) inner_a(el, indent, opts).join('') end |
#inner_a(el, indent, opts) ⇒ Object
106 107 108 109 110 111 112 |
# File 'lib/kramdown-rfc2629.rb', line 106 def inner_a(el, indent, opts) indent += INDENTATION el.children.map do |inner_el| inner_el.rfc2629_fix send("convert_#{inner_el.type}", inner_el, indent, opts) end end |
#obfuscate(text) ⇒ Object
Helper method for obfuscating the text by using XML entities.
479 480 481 482 483 484 485 486 |
# File 'lib/kramdown-rfc2629.rb', line 479 def obfuscate(text) result = "" text.each_byte do |b| result += (b > 128 ? b.chr : "&#%03d;" % b) end result.force_encoding(text.encoding) if RUBY_VERSION >= '1.9' result end |
#saner_generate_id(value) ⇒ Object
134 135 136 |
# File 'lib/kramdown-rfc2629.rb', line 134 def saner_generate_id(value) generate_id(value).gsub(/-+/, '-') end |