Class: Bizside::Redmine::HtmlToTextile::Converter

Inherits:
Nokogiri::XML::SAX::Document
  • Object
show all
Defined in:
lib/bizside/redmine/html_to_textile.rb

Overview

SAX parser

Constant Summary collapse

SHARED_TAGS =

Maps tokens for opening and closing tags

{
  # Text formatting
  :b => '**',
  :strong => '*',
}.freeze
OPENING_TAGS =

Maps tokens for opening tags

SHARED_TAGS.dup.update(
  # Headings
  :table => 'h2. ',
  :h1 => "\n h1. ",
  :h2 => 'h2. ',

  # Tables
  :th => '|_.',
  :td => '|',

  # Special
  :a => '"',

  # Structures
  :p => 'p. ',
  :br => NEWLINE,
).freeze
CLOSING_TAGS =

Maps tokens for closing tags

SHARED_TAGS.dup.update(
  # Tables
  :tr => '|',
  :td => ' ',
  :th => ' ',

  # Special
  :a => '":',
).freeze
BLOCK =

Typical block elements

[:h1, :h2, :p, :div, :table].freeze
ROW =

This is kinda a special case for block elements

[:tr, :li].freeze
INLINE =

Note that th/td in Textile are sort of inline despite truly being block

[:b, :strong, :span, :a, :th, :td].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConverter

Returns a new instance of Converter.



60
61
62
63
# File 'lib/bizside/redmine/html_to_textile.rb', line 60

def initialize
  @converted = ''
  @stack = []
end

Instance Attribute Details

#convertedObject (readonly)

Returns the value of attribute converted.



58
59
60
# File 'lib/bizside/redmine/html_to_textile.rb', line 58

def converted
  @converted
end

#originalObject (readonly)

Returns the value of attribute original.



58
59
60
# File 'lib/bizside/redmine/html_to_textile.rb', line 58

def original
  @original
end

#stackObject (readonly)

Returns the value of attribute stack.



58
59
60
# File 'lib/bizside/redmine/html_to_textile.rb', line 58

def stack
  @stack
end

Instance Method Details

#characters(text) ⇒ Object

Normal character stream



105
106
107
108
109
110
111
112
# File 'lib/bizside/redmine/html_to_textile.rb', line 105

def characters(text)
  # # Newlines should not be treated like <br /> tags, however don't indent
  # on new lines so consume any preceeding whitespace
  content = CGI.unescapeHTML(text).gsub(NEWLINE, ' ')
  content.rstrip! if content.ends_with? NEWLINE
  content.lstrip! if converted.ends_with? NEWLINE
  converted << content
end

#end_element(tag_name) ⇒ Object

Closing tag callback



90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/bizside/redmine/html_to_textile.rb', line 90

def end_element(tag_name)
  element, attribs = stack.pop
  spaces = spacing(element)
  closing = CLOSING_TAGS[element].to_s

  # Deal with cases for a/img
  converted << case element
    when :a
      special_ending(attribs['title']) + closing + attribs['href'].to_s
    else closing
  end
  append_white(spaces)
end

#start_element(tag_name, attributes = []) ⇒ Object

Opening tag callback



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/bizside/redmine/html_to_textile.rb', line 66

def start_element(tag_name, attributes = [])
  # Preprocess, and push to stack
  element = tag_name.downcase.to_sym
  attribs = Hash[attributes]
  opening = OPENING_TAGS[element].to_s.dup
  styling = prepare_styles(attribs, element)
  spaces = spacing(element)
  stack << [element, attribs]

  # Styling info gets positioned depending on element type
  content = case
    when BLOCK.include?(element)
      opening.sub('.', styling + '.')
    when ROW.include?(element)
      (styling.empty?) ? opening + ' ' : opening + styling + ('.' if :td == element).to_s + ' '
    else opening + styling
  end

  # add white space & content
  append_white(spaces)
  converted << content
end